cc-haha/desktop/src/components/workspace/WorkspaceFileOpenWith.test.tsx
程序员阿江(Relakkes) 7ca702a253 fix(desktop): simplify changed-file open-with menus
Changed-file rows are easier to scan when previewable files are grouped before source-only files, and the file open-with menu should only expose useful preview, editor, and reveal actions. Output target cards also no longer need a separate copy control now that open/open-with are the primary actions.

Constraint: Keep the existing open-with API and menu components shared across changed files, workspace context menus, and output target cards.
Rejected: Keep system-default open for files | it duplicated less predictable platform behavior and added a low-value final menu item.
Confidence: high
Scope-risk: narrow
Directive: File open-with menus should stay ordered by immediate preview/open usefulness before editor and reveal actions.
Tested: cd desktop && bun run test src/lib/openWithItems.test.ts src/components/workspace/WorkspaceFileOpenWith.test.tsx src/components/chat/AssistantOutputTargetCard.test.tsx src/components/chat/CurrentTurnChangeCard.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
2026-06-01 01:43:36 +08:00

70 lines
2.3 KiB
TypeScript

// @vitest-environment jsdom
import '@testing-library/jest-dom'
import { render, fireEvent } from '@testing-library/react'
import { describe, it, expect, vi, beforeEach } from 'vitest'
const openTarget = vi.hoisted(() => vi.fn())
const shellOpen = vi.hoisted(() => vi.fn().mockResolvedValue(undefined))
vi.mock('../../stores/openTargetStore', () => ({
useOpenTargetStore: (sel: (s: unknown) => unknown) =>
sel({
targets: [
{ id: 'code', kind: 'ide', label: 'VS Code', icon: '', platform: 'darwin' },
{ id: 'finder', kind: 'file_manager', label: 'Finder', icon: '', platform: 'darwin' },
],
ensureTargets: () => {},
openTarget,
}),
}))
vi.mock('@tauri-apps/plugin-shell', () => ({ open: shellOpen }))
vi.mock('../../i18n', () => ({
useTranslation: () => (k: string, v?: Record<string, string>) =>
v?.target ? `${k}:${v.target}` : k,
}))
import { WorkspaceFileOpenWith } from './WorkspaceFileOpenWith'
describe('WorkspaceFileOpenWith', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('renders only IDE and file-manager items', () => {
const { getAllByRole } = render(
<WorkspaceFileOpenWith absolutePath="/w/report.md" />,
)
const menuItems = getAllByRole('menuitem')
expect(menuItems).toHaveLength(2)
const labels = menuItems.map((el) => el.textContent)
expect(labels.some((l) => l?.includes('VS Code'))).toBe(true)
expect(labels.some((l) => l?.includes('Finder'))).toBe(true)
expect(labels.some((l) => l?.includes('openWith.systemDefault'))).toBe(false)
})
it('clicking the IDE item calls openTarget and onAfterSelect', () => {
const onAfter = vi.fn()
const { getAllByRole } = render(
<WorkspaceFileOpenWith absolutePath="/w/report.md" onAfterSelect={onAfter} />,
)
const menuItems = getAllByRole('menuitem')
const ideItem = menuItems.find((el) => el.textContent?.includes('VS Code'))
if (!ideItem) throw new Error('IDE menu item not found')
fireEvent.click(ideItem)
expect(openTarget).toHaveBeenCalledWith('code', '/w/report.md')
expect(onAfter).toHaveBeenCalledTimes(1)
})
it('does not call shell open from the file open-with menu', () => {
render(<WorkspaceFileOpenWith absolutePath="/w/report.md" />)
expect(shellOpen).not.toHaveBeenCalled()
})
})