/** * 复现用:新建空数据模块后 FormEditPanel 首次挂载(全部空数组)。 * 若存在响应式自触发循环,Vue 会抛 "Maximum recursive updates exceeded"。 */ import { mount } from '@vue/test-utils' import { describe, expect, it, vi } from 'vitest' import { createPinia, setActivePinia } from 'pinia' import ModuleFormEditPanel from '@/views/system/module-management/components/form-edit/FormEditPanel.vue' vi.mock('@/services/api', () => ({ loadDataApi: vi.fn(async () => ({ data: [] })), saveObjectApi: vi.fn(), nextIdApi: vi.fn(), describeApi: vi.fn(async () => ({ data: [] })), })) const StubDraggable = { name: 'draggable', props: { list: { type: Array, default: () => [] }, itemKey: { type: String, default: undefined }, }, emits: ['start', 'end'], template: `
`, } function mountEmptyPanel() { return mount(ModuleFormEditPanel, { props: { moduleId: 'm1', editConfig: [], listConfig: [], fields: [], groups: [], editMode: 'form', loading: false, active: true, }, global: { stubs: { draggable: StubDraggable } }, }) } const fields = [ { b_id: '1', b_name: '姓名', b_field: 'name', b_type: 'input' }, { b_id: '2', b_name: '年龄', b_field: 'age', b_type: 'number' }, ] const groups = [ { b_id: 'g1', b_module_id: 'm1', b_parent_id: null, b_title: '基本信息', b_xh: 10, b_canuse: 1 }, ] const editConfig = [ { b_id: 'e1', b_module_id: 'm1', b_field_id: '1', b_group_id: 'g1', b_visible: 1, b_required: 0, b_readonly: 0, b_disabled: 0, b_colspan: 24, b_height: null, b_placeholder: null, b_xh: 10 }, { b_id: 'e2', b_module_id: 'm1', b_field_id: '2', b_group_id: null, b_visible: 1, b_required: 0, b_readonly: 0, b_disabled: 0, b_colspan: 24, b_height: null, b_placeholder: null, b_xh: 20 }, ] describe('FormEditPanel 空模块挂载', () => { it('从空挂载不触发递归更新', async () => { setActivePinia(createPinia()) const wrapper = mountEmptyPanel() await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() expect(wrapper.exists()).toBe(true) wrapper.unmount() }) it('已有数据模块切到空草稿(新建模块序列)不触发递归更新', async () => { setActivePinia(createPinia()) const wrapper = mount(ModuleFormEditPanel, { props: { moduleId: 'm1', editConfig: editConfig.map((r) => ({ ...r })), listConfig: [], fields, groups: groups.map((g) => ({ ...g })), editMode: 'form', loading: false, active: true, }, global: { stubs: { draggable: StubDraggable } }, }) await wrapper.vm.$nextTick() await wrapper.vm.$nextTick() // 模拟 addModule:drafts 整体替换为空草稿,props 全部变为空数组 await wrapper.setProps({ editConfig: [], fields: [], groups: [] }) await wrapper.vm.$nextTick() await new Promise((r) => setTimeout(r, 30)) expect(wrapper.exists()).toBe(true) wrapper.unmount() }) })