120 lines
4.4 KiB
TypeScript
120 lines
4.4 KiB
TypeScript
/**
|
||
* MenuTreePanel:行尾启用勾选。
|
||
*
|
||
* 与模块树面板同构(勾选框不走 G3Tree 内置的 checkable,而是画在 #title 插槽行尾),
|
||
* 因此同样要锁住三件事:
|
||
* 1. 勾选上报 toggleEnabled,由父级落库;
|
||
* 2. 点击不冒泡(行上挂了 click 选中 / mousedown 武装拖拽);
|
||
* 3. 未保存草稿不可勾(库里没有这行),且面板必须开 block-node 才能贴到行尾。
|
||
*/
|
||
|
||
import { describe, expect, it } from 'vitest'
|
||
import { mount } from '@vue/test-utils'
|
||
import type { VueWrapper } from '@vue/test-utils'
|
||
import { G3Checkbox, G3Tree } from '@g3soft/ui'
|
||
import MenuTreePanel from '@/views/module/menu-management/MenuTreePanel.vue'
|
||
import type { MenuNode } from '@/views/module/menu-management/utils'
|
||
|
||
const TREE = [
|
||
{ b_id: 'group_base', b_name: '基础资料', b_menu_type: 'directory', b_canuse: 1 },
|
||
{ b_id: 'base_contact', b_name: '联系人', b_menu_type: 'page', b_canuse: 0 },
|
||
{ b_id: '-1', b_name: '未保存草稿', b_menu_type: 'page', b_canuse: 1 },
|
||
] as unknown as MenuNode[]
|
||
|
||
function mountPanel(unsavedIds = new Set<string>()) {
|
||
return mount(MenuTreePanel, {
|
||
props: { treeData: TREE, unsavedIds },
|
||
})
|
||
}
|
||
|
||
const rowOf = (wrapper: VueWrapper, label: string) =>
|
||
wrapper.findAll('[role="treeitem"]').find((row) => row.text().includes(label))
|
||
|
||
const checkboxOf = (wrapper: VueWrapper, label: string) =>
|
||
rowOf(wrapper, label)?.findComponent(G3Checkbox)
|
||
|
||
describe('MenuTreePanel 行尾启用勾选', () => {
|
||
it('每个节点行都带勾选框,勾选态反映 b_canuse', () => {
|
||
const wrapper = mountPanel()
|
||
|
||
expect(checkboxOf(wrapper, '基础资料')?.props('modelValue')).toBe(true)
|
||
expect(checkboxOf(wrapper, '联系人')?.props('modelValue')).toBe(false)
|
||
})
|
||
|
||
it('勾选上报 toggleEnabled(id + 目标启用态)', async () => {
|
||
const wrapper = mountPanel()
|
||
|
||
checkboxOf(wrapper, '联系人')?.vm.$emit('update:modelValue', true)
|
||
await wrapper.vm.$nextTick()
|
||
|
||
expect(wrapper.emitted('toggleEnabled')?.[0]?.[0]).toEqual({
|
||
id: 'base_contact',
|
||
enabled: true,
|
||
})
|
||
})
|
||
|
||
it('取消勾选同样上报(enabled: false)', async () => {
|
||
const wrapper = mountPanel()
|
||
|
||
checkboxOf(wrapper, '基础资料')?.vm.$emit('update:modelValue', false)
|
||
await wrapper.vm.$nextTick()
|
||
|
||
expect(wrapper.emitted('toggleEnabled')?.[0]?.[0]).toEqual({
|
||
id: 'group_base',
|
||
enabled: false,
|
||
})
|
||
})
|
||
|
||
it('点击勾选框不触发行的选中(事件不冒泡)', async () => {
|
||
const wrapper = mountPanel()
|
||
|
||
const row = rowOf(wrapper, '基础资料')!
|
||
const box = checkboxOf(wrapper, '基础资料')!.find('input')
|
||
await box.trigger('click')
|
||
|
||
expect(wrapper.emitted('select')).toBeUndefined()
|
||
// 行自身仍可正常选中,说明拦的是勾选框那一下、不是把整行点击弄坏了
|
||
await row.trigger('click')
|
||
expect(wrapper.emitted('select')?.[0]?.[0]).toBe('group_base')
|
||
})
|
||
|
||
it('未保存草稿的勾选框禁用且不上报', async () => {
|
||
const wrapper = mountPanel(new Set(['-1']))
|
||
|
||
const box = checkboxOf(wrapper, '未保存草稿')!
|
||
expect(box.props('disabled')).toBe(true)
|
||
|
||
box.vm.$emit('update:modelValue', false)
|
||
await wrapper.vm.$nextTick()
|
||
expect(wrapper.emitted('toggleEnabled')).toBeUndefined()
|
||
})
|
||
|
||
it('勾选框渲染在名称之后的行尾', () => {
|
||
const wrapper = mountPanel()
|
||
const row = rowOf(wrapper, '基础资料')!
|
||
|
||
const nameEl = row.find('.mm-tree-node__name')
|
||
const enableEl = row.find('.mm-tree-node__enable')
|
||
expect(nameEl.exists()).toBe(true)
|
||
expect(enableEl.exists()).toBe(true)
|
||
|
||
const relation = nameEl.element.compareDocumentPosition(enableEl.element)
|
||
expect(relation & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||
})
|
||
|
||
it('面板必须开 block-node:否则内容层不撑满,勾选框贴不到行尾', () => {
|
||
const wrapper = mountPanel()
|
||
|
||
// 断言落在 G3Tree 上:BizTreePanel / BizTree 是 inheritAttrs:false,
|
||
// kebab 的 'block-node' 会留在中间层的 $attrs 里(那些层取不到),
|
||
// 只有到 G3Tree 才被归一成 blockNode prop。
|
||
expect(wrapper.findComponent(G3Tree).props('blockNode')).toBe(true)
|
||
})
|
||
|
||
it('面板不启用 G3Tree 内置 checkable(避免行首出现多选勾选框)', () => {
|
||
const wrapper = mountPanel()
|
||
|
||
expect(wrapper.find('.g3-tree-node__checkbox').exists()).toBe(false)
|
||
})
|
||
})
|