cc-haha/desktop/src/components/layout/StartupErrorView.test.tsx
程序员阿江(Relakkes) 5898e02e01 fix: keep desktop copy actions reliable
Several desktop copy entry points still called navigator.clipboard directly, which can fail or report success inconsistently in Tauri and browser test contexts. Route those copy actions through the existing textarea execCommand fallback helper and cover the fallback paths for startup diagnostics, markdown copy controls, and workspace file paths.

Constraint: Clipboard API is not reliable in every desktop/browser context.

Rejected: Leave direct navigator.clipboard calls in isolated components | repeats the diagnostics copy failure mode and creates inconsistent copy behavior.

Confidence: high

Scope-risk: narrow

Directive: New desktop copy controls should use copyTextToClipboard or CopyButton instead of calling navigator.clipboard directly.

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run test -- --run src/components/markdown/MarkdownRenderer.test.tsx src/components/layout/StartupErrorView.test.tsx src/components/workspace/WorkspacePanel.test.tsx src/__tests__/diagnosticsSettings.test.tsx src/components/chat/MessageList.test.tsx

Tested: bun run check:desktop

Tested: bun run check:native

Tested: bun run check:coverage

Tested: bun run verify (passed=7 failed=0 skipped=3)

Not-tested: Live provider baseline; not required for this desktop-only clipboard fix.
2026-05-14 22:44:00 +08:00

66 lines
2.4 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { describe, expect, it, vi } from 'vitest'
import { splitStartupError, StartupErrorView } from './StartupErrorView'
describe('splitStartupError', () => {
it('separates the timeout message from captured sidecar logs', () => {
const result = splitStartupError(
'desktop server did not start listening on 127.0.0.1:57608 within 10 seconds\n\nRecent server logs:\n[stderr] failed to bind\n[exit] sidecar exited (code=1, signal=None)',
)
expect(result.message).toBe(
'desktop server did not start listening on 127.0.0.1:57608 within 10 seconds',
)
expect(result.logs).toContain('[stderr] failed to bind')
expect(result.diagnostics).toContain('Recent server logs:')
})
})
describe('StartupErrorView', () => {
it('shows diagnostics and copies the full payload with the legacy fallback', async () => {
const originalClipboard = navigator.clipboard
const originalExecCommand = document.execCommand
Object.defineProperty(document, 'execCommand', {
configurable: true,
value: vi.fn().mockReturnValue(true),
})
const execCommand = vi.mocked(document.execCommand)
const writeText = vi.fn().mockRejectedValue(new Error('clipboard blocked'))
Object.defineProperty(navigator, 'clipboard', {
value: { writeText },
configurable: true,
})
try {
render(
<StartupErrorView error={'startup failed\n\nRecent server logs:\n[stderr] boom'} />,
)
expect(screen.getByText('本地服务启动失败')).toBeInTheDocument()
expect(screen.getByText('startup failed')).toBeInTheDocument()
expect(screen.getByText('[stderr] boom')).toBeInTheDocument()
fireEvent.click(screen.getByRole('button', { name: '复制诊断信息' }))
await waitFor(() => {
expect(execCommand).toHaveBeenCalledWith('copy')
})
expect(writeText).toHaveBeenCalledWith(
'startup failed\n\nRecent server logs:\n[stderr] boom',
)
expect(screen.getByText('已复制')).toBeInTheDocument()
} finally {
Object.defineProperty(document, 'execCommand', {
configurable: true,
value: originalExecCommand,
})
Object.defineProperty(navigator, 'clipboard', {
configurable: true,
value: originalClipboard,
})
}
})
})