// @vitest-environment jsdom import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react' import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react' import type { GeneralSectionComponentProps } from '../src/client/GeneralSection.tsx' import { GeneralSection } from '../src/client/GeneralSection.tsx' import { CloseLabel, HeaderContent, TriggerContent } from '../src/client/chrome.tsx' import type { TriggerContentProps } from '../src/client/chrome.tsx' import { SettingsDocumentAction } from '../src/client/SettingsDocumentAction.tsx' import { SettingsDocumentStore } from '../src/client/settings-document-store.ts' import { en } from '../src/client/locales.ts' afterEach(cleanup) // The seat's key domain is settings ∪ common; the stub answers from the // package dictionary and falls back to the key like the real chain. const t: TriggerContentProps['t'] = key => (en as Record)[key] ?? key // Global standard kit stubs: none of these components consume the hooks. const unusedHook = (() => { throw new Error('unused by settings-general components') }) as never const kit = { useSessions: unusedHook, useWorkspaces: unusedHook } describe('chrome content', () => { it('TriggerContent renders the icon with the label in the wide column', () => { const { container } = render() expect(container.querySelector('svg')).toBeTruthy() expect(screen.getByText('Settings')).toBeTruthy() }) it('TriggerContent drops the label in the rail state', () => { const { container } = render() expect(container.querySelector('svg')).toBeTruthy() expect(screen.queryByText('Settings')).toBeNull() }) it('HeaderContent and CloseLabel render their translated text', () => { render() render() expect(screen.getByText('Settings')).toBeTruthy() expect(screen.getByText('Close')).toBeTruthy() }) }) describe('GeneralSection', () => { function mount() { const renderSlot = vi.fn( ((key: string) =>
) as GeneralSectionComponentProps['renderSlot'], ) const props: GeneralSectionComponentProps = { ...kit, renderSlot } const view = render() return { view, renderSlot } } it('renders the item slot as the section body', () => { const { renderSlot } = mount() expect(renderSlot).toHaveBeenCalledWith('settings.general.item', {}) expect(screen.getByTestId('slot-settings.general.item')).toBeTruthy() }) }) describe('SettingsDocumentAction', () => { it('appears only for a file-backed provider and requests its Host-owned document', async () => { const openDocument = vi.fn(() => Promise.resolve({ rpcId: 'document-open' as never, result: { ok: true as const, value: { opened: true as const } }, })) const controller = new SettingsDocumentStore({ settings: { describe: vi.fn(() => Promise.resolve({ rpcId: 'document-action' as never, result: { ok: true as const, value: { writable: true, hasDocument: true, namespaces: [] }, }, })), openDocument, }, } as never) render() const action = await screen.findByRole('button', { name: 'Open configuration file' }) fireEvent.click(action) await waitFor(() => { expect(openDocument).toHaveBeenCalledWith({}) }) }) it('stays absent without a document and retries availability after remount', async () => { const describe = vi.fn() .mockResolvedValueOnce({ rpcId: 'document-action-absent' as never, result: { ok: true as const, value: { writable: true, hasDocument: false, namespaces: [] } }, }) .mockResolvedValueOnce({ rpcId: 'document-action-ready' as never, result: { ok: true as const, value: { writable: true, hasDocument: true, namespaces: [] } }, }) const controller = new SettingsDocumentStore({ settings: { describe, openDocument: vi.fn(), }, } as never) const first = render() await waitFor(() => { expect(controller.store.getSnapshot().status).toBe('unavailable') }) expect(screen.queryByRole('button', { name: 'Open configuration file' })).toBeNull() first.unmount() render() expect(await screen.findByRole('button', { name: 'Open configuration file' })).toBeTruthy() expect(describe).toHaveBeenCalledTimes(2) }) it('keeps the action available and reports a native-open failure', async () => { const controller = new SettingsDocumentStore({ settings: { describe: vi.fn(() => Promise.resolve({ rpcId: 'document-action' as never, result: { ok: true as const, value: { writable: true, hasDocument: true, namespaces: [] }, }, })), openDocument: vi.fn(() => Promise.resolve({ rpcId: 'document-open-failed' as never, result: { ok: false as const, error: { code: 'internal' as const, message: 'xdg-open missing', details: {} } }, })), }, } as never) render() fireEvent.click(await screen.findByRole('button', { name: 'Open configuration file' })) expect((await screen.findByRole('alert')).textContent).toBe('Could not open configuration file') expect(screen.getByRole('button', { name: 'Open configuration file' })).toBeTruthy() }) })