20260915221013

This commit is contained in:
oneao committed 2026-09-15 22:10:13 +08:00
1 parent 1f56cc3efb
commit dce29f250e
54 files changed
+3732 -574

No files matched your search

@@ -118,9 +118,9 @@ describe('FmsTree 虚拟根(showRoot)', () => {
const rows = wrapper.findAll('.tree-node')
expect(rows).toHaveLength(2)
expect(rows[0].text()).toContain('全部分类')
// 有子节点:根不是叶子,渲染真实折叠箭头(不是 is-placeholder 占位)
// 有子节点:根不是叶子,渲染折叠箭头
expect(rows[0].classes()).not.toContain('is-leaf')
expect(rows[0].find('.tree-node-switcher:not(.is-placeholder)').exists()).toBe(true)
expect(rows[0].find('.tree-node-switcher').exists()).toBe(true)
// 调用方的 expandedKeys 为空,根的子节点依然可见
expect(rows[1].text()).toContain('根节点')
})
@@ -130,7 +130,7 @@ describe('FmsTree 虚拟根(showRoot)', () => {
const rows = wrapper.findAll('.tree-node')
expect(rows).toHaveLength(1)
expect(rows[0].classes()).not.toContain('is-leaf')
expect(rows[0].find('.tree-node-switcher:not(.is-placeholder)').exists()).toBe(true)
expect(rows[0].find('.tree-node-switcher').exists()).toBe(true)
})
it('根节点以 rootKey 作为 key,业务节点不带根 key', () => {
@@ -161,19 +161,19 @@ describe('FmsTree 虚拟根(showRoot)', () => {
expect(wrapper.findAll('.tree-node')).toHaveLength(2)
// 第一个真实展开按钮属于虚拟根:点击收起整棵树
await wrapper.find('.tree-node-switcher:not(.is-placeholder)').trigger('click')
await wrapper.find('.tree-node-switcher').trigger('click')
await nextTick()
expect(wrapper.findAll('.tree-node')).toHaveLength(1)
expect(wrapper.emitted('update:expandedKeys')[0][0]).not.toContain('__fms_tree_root__')
// 再点一次展开,业务节点回来
await wrapper.find('.tree-node-switcher:not(.is-placeholder)').trigger('click')
await wrapper.find('.tree-node-switcher').trigger('click')
await nextTick()
expect(wrapper.findAll('.tree-node')).toHaveLength(2)
expect(wrapper.find('.tree-node-content').text()).toBe('全部分类')
// 业务节点自己的展开按钮照常工作
await wrapper.findAll('.tree-node-switcher:not(.is-placeholder)')[1].trigger('click')
await wrapper.findAll('.tree-node-switcher')[1].trigger('click')
await nextTick()
expect(wrapper.findAll('.tree-node')).toHaveLength(3)
})
@@ -184,6 +184,96 @@ describe('FmsTree 虚拟根(showRoot)', () => {
})
})
describe('FmsTree 虚拟根的选中约定(showRoot)', () => {
it('selectedKeys 为空时虚拟根呈现选中态,调用方无需传 rootKey', () => {
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), showRoot: true, selectedKeys: [] },
})
// 第一个节点是虚拟根,应带上选中类
expect(wrapper.findAll('.tree-node')[0].classes()).toContain('is-selected')
})
it('未传 selectedKeys 时同样把虚拟根当作选中(默认选中「全部」)', () => {
const wrapper = mount(FmsTree, { props: { treeData: makeTreeData(), showRoot: true } })
expect(wrapper.findAll('.tree-node')[0].classes()).toContain('is-selected')
})
it('选中业务节点时虚拟根不再高亮', () => {
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), showRoot: true, selectedKeys: ['1'] },
})
const rows = wrapper.findAll('.tree-node')
expect(rows[0].classes()).not.toContain('is-selected')
expect(rows[1].classes()).toContain('is-selected')
})
it('点中虚拟根时 select 回传空数组,调用方看不到 rootKey', async () => {
const onSelect = vi.fn()
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), showRoot: true },
attrs: { onSelect },
})
await wrapper.findAll('.tree-node-content')[0].trigger('click')
expect(onSelect).toHaveBeenCalledTimes(1)
// 归一化成 [],而不是 ['__fms_tree_root__']
expect(onSelect.mock.calls[0][0]).toEqual([])
})
it('点中业务节点时 select 原样回传该节点的 key', async () => {
const onSelect = vi.fn()
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), showRoot: true },
attrs: { onSelect },
})
await wrapper.findAll('.tree-node-content')[1].trigger('click')
expect(onSelect.mock.calls[0][0]).toEqual(['1'])
})
it('无虚拟根时不改写 selectedKeys,也不改写 select 回传值', async () => {
const onSelect = vi.fn()
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), selectedKeys: [] },
attrs: { onSelect },
})
expect(wrapper.find('.tree-node').classes()).not.toContain('is-selected')
await wrapper.find('.tree-node-content').trigger('click')
expect(onSelect.mock.calls[0][0]).toEqual(['1'])
})
})
describe('FmsTree 加载态(loading)', () => {
it('loading=false 时不渲染遮罩', () => {
const wrapper = mount(FmsTree, { props: { treeData: makeTreeData() } })
expect(wrapper.find('.fms-tree__loading').exists()).toBe(false)
})
it('loading=true 时渲染遮罩,且树仍在渲染(不是 v-else 替换)', () => {
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), loading: true },
})
expect(wrapper.find('.fms-tree__loading').exists()).toBe(true)
// 遮罩是覆盖层,业务节点照常存在,避免加载完成后尺寸跳动
expect(wrapper.find('.tree-node-content').text()).toBe('根节点')
})
it('#loading 插槽可覆盖默认的 Spin', () => {
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), loading: true },
slots: { loading: () => h('span', { class: 'my-loading' }, '载入中') },
})
expect(wrapper.find('.my-loading').text()).toBe('载入中')
})
it('loading=false 时 #loading 插槽不渲染', () => {
const wrapper = mount(FmsTree, {
props: { treeData: makeTreeData(), loading: false },
slots: { loading: () => h('span', { class: 'my-loading' }, '载入中') },
})
expect(wrapper.find('.my-loading').exists()).toBe(false)
})
})
describe('FmsTree 事件透传', () => {
it('select 事件原样透传给调用方', async () => {
const onSelect = vi.fn()