20260824172723

This commit is contained in:
oneao committed 2026-08-24 17:27:24 +08:00
1 parent 791d1e01d7
commit 97aea665f9
10 files changed
+443 -723

No files matched your search

@@ -220,12 +220,19 @@ describe('模块管理页面(重构后)', () => {
const wrapper = await mountPage()
await selectModule(wrapper, '订单')
// 分组导航渲染:概览 / 数据结构 / 界面配置 / 业务能力 / 高级设置
const groupTitles = wrapper.findAll('.mm-config-nav__group-title').map((t) => t.text())
expect(groupTitles).toEqual(['概览', '数据结构', '界面配置', '业务能力', '高级设置'])
// 横向导航渲染全部配置项(无分组小标题)
const labels = wrapper.findAll('.mm-config-nav__label').map((t) => t.text())
expect(labels).toContain('基本信息')
expect(labels).toContain('字段定义')
expect(labels).toContain('表单设计')
expect(labels).toContain('列表配置')
expect(labels).toContain('查询配置')
expect(labels).toContain('自动编码')
expect(labels).toContain('权限')
expect(labels).toContain('多语言')
// 仅一个激活项(基本信息)
const active = wrapper.findAll('.mm-config-nav__item.is-active')
const active = wrapper.findAll('.mm-config-nav .tabs-tab-active')
expect(active).toHaveLength(1)
expect(active[0].text()).toContain('基本信息')
})
@@ -235,13 +242,13 @@ describe('模块管理页面(重构后)', () => {
await selectModule(wrapper, '订单')
const fieldsItem = wrapper
.findAll('.mm-config-nav__item')
.findAll('.mm-config-nav .tabs-tab')
.find((el) => el.text().includes('字段定义'))
expect(fieldsItem).toBeTruthy()
await fieldsItem.trigger('click')
await nextTick()
const active = wrapper.findAll('.mm-config-nav__item.is-active')
const active = wrapper.findAll('.mm-config-nav .tabs-tab-active')
expect(active).toHaveLength(1)
expect(active[0].text()).toContain('字段定义')
// 对应内容面板显示
@@ -300,8 +307,8 @@ describe('模块管理页面(重构后)', () => {
await nextTick()
expect(nextIdApi).toHaveBeenCalled()
// 新建草稿标记「未保存」
expect(wrapper.text()).toContain('未保存')
// 新建草稿:选中新节点(is-selected 生效)
expect(moduleTreeOf(wrapper).find('.is-selected').exists()).toBe(true)
})
it('右键模块节点:删除确认弹窗为 danger 按钮', async () => {
@@ -428,11 +435,11 @@ describe('模块管理页面(重构后)', () => {
expect(labels).toContain('新增查询模块')
})
it('分类节点:分组导航仅显示概览(无数据结构/展示配置/业务能力/多语言)', async () => {
it('分类节点:分组导航仅显示基本信息(无数据结构/展示配置/业务能力/多语言)', async () => {
const wrapper = await mountPage()
await selectModule(wrapper, '系统')
const titles = wrapper.findAll('.mm-config-nav__group-title').map((t) => t.text())
expect(titles).toEqual(['概览'])
const labels = wrapper.findAll('.mm-config-nav__label').map((t) => t.text())
expect(labels).toEqual(['基本信息'])
})
it('查询模块:分组导航无「表单设计」「自动编码」', async () => {
@@ -440,7 +447,6 @@ describe('模块管理页面(重构后)', () => {
await selectModule(wrapper, '查询A')
const labels = wrapper.findAll('.mm-config-nav__label').map((t) => t.text())
expect(labels).toContain('字段定义')
expect(labels).toContain('分组管理')
expect(labels).toContain('查询配置')
expect(labels).not.toContain('表单设计')
expect(labels).not.toContain('自动编码')
@@ -490,8 +496,8 @@ describe('模块管理页面(重构后)', () => {
await flushPromises()
await nextTick()
// 新建草稿:显示「未保存」
expect(wrapper.text()).toContain('未保存')
// 新建草稿:选中新节点
expect(moduleTreeOf(wrapper).find('.is-selected').exists()).toBe(true)
// 通过基本信息 stub 补齐必填字段
const basicStub = wrapper.findComponent({ name: 'ModuleBasicPanel' })
@@ -520,8 +526,8 @@ describe('模块管理页面(重构后)', () => {
const moduleReq = reqs.find((r) => r.table === 's_module')
expect(moduleReq).toBeTruthy()
expect(moduleReq.inserts).toBeTruthy()
// 保存成功后未保存标记清除
expect(wrapper.text()).not.toContain('未保存')
// 保存成功后仍选中新节点
expect(moduleTreeOf(wrapper).find('.is-selected').exists()).toBe(true)
})
it('重载:有未保存修改时弹出确认', async () => {
@@ -563,8 +569,8 @@ describe('模块管理页面(重构后)', () => {
await cancelBtn.trigger('click')
await nextTick()
// 未切换:header 仍是「订单」
expect(wrapper.find('.mm-header__name').text()).toContain('订单')
// 未切换:树节点仍是「订单」
expect(moduleTreeOf(wrapper).find('.is-selected').text()).toContain('订单')
})
it('切换保护:放弃修改 → 切换到目标节点', async () => {
@@ -587,7 +593,7 @@ describe('模块管理页面(重构后)', () => {
await nextTick()
// 已切换到「系统」
expect(wrapper.find('.mm-header__name').text()).toContain('系统')
expect(moduleTreeOf(wrapper).find('.is-selected').text()).toContain('系统')
})
it('切换保护:保存并切换 → 先保存再切换', async () => {
@@ -612,7 +618,7 @@ describe('模块管理页面(重构后)', () => {
expect(saveObjectApi).toHaveBeenCalled()
// 已切换到「系统」
expect(wrapper.find('.mm-header__name').text()).toContain('系统')
expect(moduleTreeOf(wrapper).find('.is-selected').text()).toContain('系统')
})
it('删除确认后执行:调用 saveObjectApi(含子表删除)', async () => {
@@ -770,21 +776,21 @@ describe('模块管理页面(重构后)', () => {
await nextTick()
const nav = wrapper.findAll('.mm-config-nav').at(-1)
const titles = nav.findAll('.mm-config-nav__group-title').map((t) => t.text())
expect(titles).toEqual(['概览', '业务能力', '高级设置'])
const labels = nav.findAll('.mm-config-nav__label').map((t) => t.text())
expect(labels).toEqual(['基本信息', '权限配置', '多语言'])
// 仅一个激活项(基本信息)
expect(nav.findAll('.mm-config-nav__item.is-active')).toHaveLength(1)
expect(nav.findAll('.mm-config-nav__item.is-active')[0].text()).toContain('基本信息')
expect(nav.findAll('.tabs-tab-active')).toHaveLength(1)
expect(nav.findAll('.tabs-tab-active')[0].text()).toContain('基本信息')
// 点击「权限配置」→ 激活态切换,activeSection 同步到面板
const powersItem = nav
.findAll('.mm-config-nav__item')
.findAll('.tabs-tab')
.find((el) => el.text().includes('权限配置'))
expect(powersItem).toBeTruthy()
await powersItem.trigger('click')
await nextTick()
expect(nav.findAll('.mm-config-nav__item.is-active')).toHaveLength(1)
expect(nav.findAll('.mm-config-nav__item.is-active')[0].text()).toContain('权限配置')
expect(nav.findAll('.tabs-tab-active')).toHaveLength(1)
expect(nav.findAll('.tabs-tab-active')[0].text()).toContain('权限配置')
const menuStub = wrapper.findComponent({ name: 'MenuDetailPanel' })
expect(menuStub.attributes('active-section')).toBe('powers')
})
@@ -802,53 +808,12 @@ describe('模块管理页面(重构后)', () => {
await nextTick()
const nav = wrapper.findAll('.mm-config-nav').at(-1)
expect(nav.findAll('.mm-config-nav__group-title').map((t) => t.text())).toEqual([
'概览',
'高级设置',
expect(nav.findAll('.mm-config-nav__label').map((t) => t.text())).toEqual([
'基本信息',
'多语言',
])
expect(nav.text()).not.toContain('权限配置')
})
it('点击导航「分组管理」:激活分区并打开分组管理弹窗', async () => {
const wrapper = await mountPage()
await selectModule(wrapper, '订单')
const groupsItem = wrapper
.findAll('.mm-config-nav__item')
.find((el) => el.text().includes('分组管理'))
expect(groupsItem).toBeTruthy()
await groupsItem.trigger('click')
await nextTick()
// 分组管理是唯一激活项,弹窗打开(FieldGroupManager 内容)
const active = wrapper.findAll('.mm-config-nav__item.is-active')
expect(active).toHaveLength(1)
expect(active[0].text()).toContain('分组管理')
const modal = wrapper.find('.stub-modal')
expect(modal.exists()).toBe(true)
// 简化后的分组管理:顶部输入框即新增(不再有「新增根分组」按钮)
expect(modal.find('.mm-groups__input').exists()).toBe(true)
expect(modal.text()).toContain('将添加为顶级分组')
})
it('点击其他导航项:分组管理弹窗自动关闭', async () => {
const wrapper = await mountPage()
await selectModule(wrapper, '订单')
const groupsItem = wrapper
.findAll('.mm-config-nav__item')
.find((el) => el.text().includes('分组管理'))
await groupsItem.trigger('click')
await nextTick()
expect(wrapper.find('.stub-modal').exists()).toBe(true)
const fieldsItem = wrapper
.findAll('.mm-config-nav__item')
.find((el) => el.text().includes('字段定义'))
await fieldsItem.trigger('click')
await nextTick()
expect(wrapper.find('.stub-modal').exists()).toBe(false)
})
})
describe('ModuleBasicPanel(基本信息面板)', () => {
@@ -1026,7 +991,7 @@ describe('MenuDetailPanel', () => {
})
})
// 放置意图:在目标卡片上 stub rect 并触发原生 dragover,由画布容器监听器记录意图
// 放置意图:在目标卡片上 stub rect 并触发 mousemove(fallback 模式下意图检测挂在 window mousemove)
async function hoverCard(wrapper, fieldId, rect, clientX, clientY) {
const card = wrapper.find(`.mm-fdesign__field[data-field-id="${fieldId}"]`)
card.element.getBoundingClientRect = () => ({
@@ -1037,7 +1002,9 @@ async function hoverCard(wrapper, fieldId, rect, clientX, clientY) {
right: rect.left + rect.width,
bottom: rect.top + rect.height,
})
await card.trigger('dragover', { clientX, clientY })
card.element.dispatchEvent(
new MouseEvent('mousemove', { clientX, clientY, bubbles: true, cancelable: true }),
)
}
// 构造拖拽 start/end 事件的 item 元素(带 data-field-id)
@@ -1110,6 +1077,7 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
Draggable: stubDraggable,
},
},
attachTo: document.body,
})
// 快速构造画布行(拖拽用例通用)
@@ -1748,7 +1716,10 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
.find('.mm-fdesign__grid-empty')
.element.closest('.mm-fdesign__section')
await simulateLibDrop(wrapper, extraFields[3], async () => {
emptySectionEl.dispatchEvent(new Event('dragover', { bubbles: true }))
// fallback 模式:意图检测挂在 window mousemove 上
emptySectionEl.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 100, clientY: 100 }),
)
})
const updates = wrapper.emitted('update')
@@ -2031,7 +2002,10 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
?.closest('.mm-fdesign__section')
expect(emptySectionEl).toBeTruthy()
await simulateCardDrop(wrapper, target, 'f3', async () => {
emptySectionEl.dispatchEvent(new Event('dragover', { bubbles: true }))
// fallback 模式:意图检测挂在 window mousemove 上
emptySectionEl.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 100, clientY: 100 }),
)
})
const last = wrapper.emitted('update').at(-1)[0]
const moved = last.find((r) => r.b_field_id === 'f3')
@@ -2061,7 +2035,10 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
?.closest('.mm-fdesign__section')
expect(emptySectionEl).toBeTruthy()
await simulateCardDrop(wrapper, target, 'f2', async () => {
emptySectionEl.dispatchEvent(new Event('dragover', { bubbles: true }))
// fallback 模式:意图检测挂在 window mousemove 上
emptySectionEl.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 100, clientY: 100 }),
)
})
const last = wrapper.emitted('update').at(-1)[0]
expect(last.find((r) => r.b_field_id === 'f2').b_group_id).toBe('g2')
@@ -2151,10 +2128,10 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
target.vm.$emit('start', { item: itemEl('f2') })
// 先悬停 f1 记录意图
await hoverCard(wrapper, 'f1', { top: 10, height: 60, left: 0, width: 200 }, 180, 40)
// 拖出画布区域(dragleave,relatedTarget 不在画布内)
await wrapper
.find('.mm-fdesign__canvas-wrap')
.trigger('dragleave', { relatedTarget: null })
// 拖出画布区域(fallback 模式:mousemove 到画布外的 body,意图被清除)
await document.body.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 5, clientY: 5 }),
)
// 松手
target.vm.$emit('end', { item: itemEl('f2') })
await nextTick()
@@ -2191,7 +2168,10 @@ describe('ModuleEditConfigPanel(表单设计视图)', () => {
const ungroupedSection = wrapper.find('[data-section-key="ungrouped"]')
expect(ungroupedSection.exists()).toBe(true)
await simulateLibDrop(wrapper, extraFields[3], async () => {
ungroupedSection.element.dispatchEvent(new Event('dragover', { bubbles: true }))
// fallback 模式:意图检测挂在 window mousemove 上
ungroupedSection.element.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 100, clientY: 100 }),
)
})
const last = wrapper.emitted('update').at(-1)[0]
const row = last.find((r) => r.b_field_id === 'f4')