test: App 与 main 函数覆盖提升至 90%+(右键操作/右侧面板/解码回退/入口)

This commit is contained in:
2026-08-17 18:18:25 +08:00
parent c95e18f66e
commit 05f05a29ee
2 changed files with 106 additions and 0 deletions
+86
View File
@@ -18,10 +18,18 @@ function mockApi(overrides?: Partial<typeof window.api>): typeof window.api {
return { ...base, ...overrides } as typeof window.api return { ...base, ...overrides } as typeof window.api
} }
let clipboardSpy: ReturnType<typeof vi.fn>
beforeEach(() => { beforeEach(() => {
window.api = mockApi() window.api = mockApi()
// jsdom 未实现 scrollIntoView,导航定位需要打桩 // jsdom 未实现 scrollIntoView,导航定位需要打桩
Element.prototype.scrollIntoView = vi.fn() Element.prototype.scrollIntoView = vi.fn()
// jsdom 未实现 navigator.clipboard,右键复制需要打桩
clipboardSpy = vi.fn()
Object.defineProperty(navigator, 'clipboard', {
value: { writeText: clipboardSpy },
configurable: true
})
}) })
describe('App - 初始空态', () => { describe('App - 初始空态', () => {
@@ -105,6 +113,19 @@ describe('App - 拖拽导入', () => {
fireEvent.dragLeave(pane) fireEvent.dragLeave(pane)
expect(pane.className).not.toContain('dragging') expect(pane.className).not.toContain('dragging')
}) })
it('解码失败时回退 file.text(覆盖 dropPane catch 分支)', async () => {
window.api = mockApi({
decodeBuffer: async () => {
throw new Error('boom')
}
})
render(<App />)
const file = new File(['fallback1'], 'd.txt', { type: 'text/plain' })
const pane = screen.getByText(/选择左侧文件/).closest('.pane-empty') as Element
fireEvent.drop(pane, { dataTransfer: { files: [file] } })
expect(await screen.findByText('导出报告')).toBeInTheDocument()
})
}) })
describe('App - 差异导航与清空', () => { describe('App - 差异导航与清空', () => {
@@ -125,3 +146,68 @@ describe('App - 差异导航与清空', () => {
expect(await screen.findByText(/选择左侧文件/)).toBeInTheDocument() expect(await screen.findByText(/选择左侧文件/)).toBeInTheDocument()
}) })
}) })
describe('App - 空态打开按钮', () => {
it('点击空面板的打开文件按钮加载左侧文件', async () => {
render(<App />)
fireEvent.click(screen.getAllByText('打开文件')[0])
expect(await screen.findByText('导出报告')).toBeInTheDocument()
})
})
describe('App - 右键菜单操作', () => {
it('执行复制本行内容并关闭菜单', async () => {
render(<App />)
fireEvent.click(screen.getByText('打开左侧'))
await screen.findByText('导出报告')
fireEvent.contextMenu((await screen.findAllByText(/line1/))[0])
fireEvent.click(await screen.findByText('复制左侧此行内容'))
expect(clipboardSpy).toHaveBeenCalled()
expect(screen.queryByText('复制左侧此行内容')).not.toBeInTheDocument()
})
it('执行复制文件名', async () => {
render(<App />)
fireEvent.click(screen.getByText('打开左侧'))
await screen.findByText('导出报告')
fireEvent.contextMenu((await screen.findAllByText(/line1/))[0])
fireEvent.click(await screen.findByText('复制文件名'))
expect(clipboardSpy).toHaveBeenCalledWith('a.txt')
})
it('执行在文件夹中显示(覆盖 showInFolder', async () => {
const showInFolder = vi.fn(async () => true)
window.api = mockApi({ showInFolder })
render(<App />)
fireEvent.click(screen.getByText('打开左侧'))
await screen.findByText('导出报告')
fireEvent.contextMenu((await screen.findAllByText(/line1/))[0])
fireEvent.click(await screen.findByText('在文件夹中显示'))
expect(showInFolder).toHaveBeenCalledWith('/tmp/a.txt')
})
})
describe('App - 右侧面板交互', () => {
it('点击右侧打开文件按钮加载', async () => {
render(<App />)
fireEvent.click(screen.getAllByText('打开文件')[1])
expect(await screen.findByText('导出报告')).toBeInTheDocument()
})
it('右侧拖拽悬停/离开高亮切换', () => {
render(<App />)
const pane = screen.getByText(/选择右侧文件/).closest('.pane-empty') as Element
fireEvent.dragOver(pane)
expect(pane.className).toContain('dragging')
fireEvent.dragLeave(pane)
expect(pane.className).not.toContain('dragging')
})
it('右侧拖放加载(覆盖右侧 onDrop 与 dropPane 右分支)', async () => {
render(<App />)
const file = new File(['r1\nr2'], 'e.txt', { type: 'text/plain' })
const pane = screen.getByText(/选择右侧文件/).closest('.pane-empty') as Element
fireEvent.drop(pane, { dataTransfer: { files: [file] } })
expect(await screen.findByText('导出报告')).toBeInTheDocument()
})
})
+20
View File
@@ -0,0 +1,20 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { screen, act } from '@testing-library/react'
// main.tsx 引入全局样式,测试中替换为空模块避免 CSS 处理
vi.mock('../styles/global.css', () => ({}))
describe('main 入口', () => {
beforeEach(() => {
document.body.innerHTML = '<div id="root"></div>'
vi.resetModules()
})
it('挂载 DiffLens 应用(覆盖 main.tsx 入口)', async () => {
await act(async () => {
await import('../main')
})
expect(document.getElementById('root')).toBeTruthy()
expect(await screen.findByText('DiffLens')).toBeInTheDocument()
})
})