fix(sidebar): 侧边栏四项反馈(docs/17)
空状态按钮对齐页签缩进;启动自动恢复上次工作区(prefs 存 lastWorkspace、 启动校验存在性);空文件夹展开显示「(空)」、文件夹行加粗(展开逻辑经 组件测试证实本就可用);新建泛化到任意文件夹:树头+文档/+文件夹、 文件夹右键在此新建文档/文件夹。vitest 86 通过 + 2 跳过。
This commit is contained in:
101
tests/sidebar-tree.test.tsx
Normal file
101
tests/sidebar-tree.test.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
// 文件树回归:子文件夹展开、空文件夹提示、文件夹右键新建文档/文件夹。
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { act } from 'react-dom/test-utils'
|
||||
|
||||
vi.mock('../src/services/platform', async (importOriginal) => {
|
||||
const orig = await importOriginal<typeof import('../src/services/platform')>()
|
||||
return {
|
||||
...orig,
|
||||
listDir: async (dir: string) => {
|
||||
if (dir === 'C:/ws') {
|
||||
return [
|
||||
{ name: 'sub', path: 'C:/ws/sub', isDir: true },
|
||||
{ name: 'empty', path: 'C:/ws/empty', isDir: true },
|
||||
{ name: 'a.md', path: 'C:/ws/a.md', isDir: false },
|
||||
]
|
||||
}
|
||||
if (dir === 'C:/ws/sub') return [{ name: 'b.md', path: 'C:/ws/sub/b.md', isDir: false }]
|
||||
return []
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
import Sidebar from '../src/components/Sidebar'
|
||||
|
||||
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
|
||||
|
||||
async function renderSidebar(extra: Record<string, unknown> = {}) {
|
||||
const container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
const root = createRoot(container)
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<Sidebar
|
||||
mode="files"
|
||||
onModeChange={() => undefined}
|
||||
workspaceRoot="C:/ws"
|
||||
activePath={null}
|
||||
onOpenFile={() => undefined}
|
||||
onOpenFolder={() => undefined}
|
||||
outline={[]}
|
||||
onJumpHeading={() => undefined}
|
||||
tauriMode
|
||||
{...extra}
|
||||
/>,
|
||||
)
|
||||
})
|
||||
await act(async () => { await sleep(30) })
|
||||
return { container, root }
|
||||
}
|
||||
|
||||
function findButton(container: HTMLElement, text: string) {
|
||||
return [...container.querySelectorAll('button')].find((b) => b.textContent?.includes(text))
|
||||
}
|
||||
|
||||
describe('文件树', () => {
|
||||
it('子文件夹点击展开能看到下级文件', async () => {
|
||||
const { container, root } = await renderSidebar()
|
||||
await act(async () => {
|
||||
findButton(container, 'sub')?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
})
|
||||
await act(async () => { await sleep(30) })
|
||||
expect(container.innerHTML).toContain('b.md')
|
||||
await act(async () => { root.unmount() })
|
||||
container.remove()
|
||||
})
|
||||
|
||||
it('空文件夹展开后有(空)提示而不是空白', async () => {
|
||||
const { container, root } = await renderSidebar()
|
||||
await act(async () => {
|
||||
findButton(container, 'empty')?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
})
|
||||
await act(async () => { await sleep(30) })
|
||||
expect(container.innerHTML).toContain('(空)')
|
||||
await act(async () => { root.unmount() })
|
||||
container.remove()
|
||||
})
|
||||
|
||||
it('文件夹右键菜单有新建文档/文件夹并回传该文件夹', async () => {
|
||||
const created: string[] = []
|
||||
const folders: string[] = []
|
||||
const { container, root } = await renderSidebar({
|
||||
onCreateFileIn: (dir: string) => created.push(dir),
|
||||
onCreateFolderIn: (dir: string) => folders.push(dir),
|
||||
})
|
||||
await act(async () => {
|
||||
findButton(container, 'sub')?.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true }))
|
||||
})
|
||||
await act(async () => { await sleep(10) })
|
||||
const fileItem = findButton(container, '在此新建文档')
|
||||
const folderItem = findButton(container, '在此新建文件夹')
|
||||
expect(fileItem).toBeTruthy()
|
||||
expect(folderItem).toBeTruthy()
|
||||
await act(async () => {
|
||||
fileItem?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
||||
})
|
||||
expect(created).toEqual(['C:/ws/sub'])
|
||||
await act(async () => { root.unmount() })
|
||||
container.remove()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user