import { mount } from '@vue/test-utils' import { describe, expect, it, vi, beforeAll, beforeEach } from 'vitest' import { createPinia, setActivePinia } from 'pinia' import { nextTick } from 'vue' import { registerFeature, useAreaSelection } from 'stk-table-vue' import ModuleQueryConfigPanel from '@/views/module/module-management/ModuleQueryConfigPanel.vue' import ModuleI18nPanel from '@/views/module/module-management/ModuleI18nPanel.vue' registerFeature(useAreaSelection) beforeAll(() => { Object.defineProperty(HTMLElement.prototype, 'clientWidth', { configurable: true, get() { return 5000 }, }) }) vi.mock('@/services/api', () => ({ loadDataApi: vi.fn(async () => ({ data: [] })), saveObjectApi: vi.fn(), nextIdApi: vi.fn(), describeApi: vi.fn(), })) const fields = [{ b_id: '1', b_name: '姓名', b_field: 'name', b_type: 'input', b_canuse: 1 }] /** 受控 rows 模型:把最后一次 update:rows 回灌到 props,模拟父级 v-model */ async function syncRows(wrapper) { const events = wrapper.emitted('update:rows') if (events && events.length) { await wrapper.setProps({ rows: events.at(-1)[0] }) } await nextTick() await new Promise((r) => setTimeout(r, 20)) } describe('module-management 删除(单个无确认弹窗 + 批量)', () => { beforeEach(() => setActivePinia(createPinia())) async function settle() { await nextTick() await new Promise((r) => setTimeout(r, 50)) } async function clickDelete(wrapper) { const trs = wrapper.findAll('.stk-tbody-main tr') expect(trs.length).toBeGreaterThan(0) const delBtn = trs[0].find('button.fms-action-btn') expect(delBtn, '行内删除按钮应存在').toBeTruthy() await delBtn.trigger('click') await settle() } async function checkNoModal() { expect(document.body.querySelector('.fms-modal'), '删除不应弹出确认弹窗').toBeNull() } async function selectRowCheckbox(wrapper, index = 0) { const trs = wrapper.findAll('.stk-tbody-main tr') expect(trs.length).toBeGreaterThan(0) const checkbox = trs[index].find('input[type="checkbox"]') expect(checkbox, '行复选框应存在').toBeTruthy() await checkbox.setValue(true) await settle() } async function clickToolbarBatch(wrapper) { const btn = wrapper.findAll('button').find((b) => b.text().includes('批量删除')) expect(btn, '批量删除按钮应存在').toBeTruthy() await btn.trigger('click') await settle() } async function clickToolbarAdd(wrapper, label) { const btn = wrapper.findAll('button').find((b) => b.text().includes(label)) expect(btn, `${label} 按钮应存在`).toBeTruthy() await btn.trigger('click') await settle() } it('查询面板:单个删除不弹弹窗且行被移除', async () => { const wrapper = mount(ModuleQueryConfigPanel, { props: { moduleId: 'm1', queryConfig: [], fields, loading: false }, attachTo: document.body, }) await settle() await clickToolbarAdd(wrapper, '新增查询条件') expect(wrapper.findAll('.stk-tbody-main tr').length).toBe(1) await clickDelete(wrapper) await checkNoModal() expect(wrapper.findAll('.stk-tbody-main tr').length, '单个删除后行应被移除').toBe(0) wrapper.unmount() }) it('查询面板:批量删除选中多行', async () => { const wrapper = mount(ModuleQueryConfigPanel, { props: { moduleId: 'm1', queryConfig: [], fields, loading: false }, attachTo: document.body, }) await settle() for (let i = 0; i < 2; i++) { await clickToolbarAdd(wrapper, '新增查询条件') } expect(wrapper.findAll('.stk-tbody-main tr').length).toBe(2) await selectRowCheckbox(wrapper, 0) await selectRowCheckbox(wrapper, 1) await clickToolbarBatch(wrapper) await checkNoModal() expect(wrapper.findAll('.stk-tbody-main tr').length, '批量删除后应无行').toBe(0) wrapper.unmount() }) it('多语言面板:新增/单个删除通过 update:rows 上报且不弹弹窗', async () => { const wrapper = mount(ModuleI18nPanel, { props: { rows: [], languages: [ { code: 'zh-CN', name: '简体中文', default: true }, { code: 'en-US', name: 'English', default: false }, ], loading: false, }, attachTo: document.body, }) await settle() await clickToolbarAdd(wrapper, '新增多语言') await syncRows(wrapper) const rowsAfterAdd = wrapper.props('rows') expect(rowsAfterAdd.length).toBe(1) expect(rowsAfterAdd[0]._managedId, '手动新增行不受管,可删除').toBeUndefined() await clickDelete(wrapper) await syncRows(wrapper) await checkNoModal() expect(wrapper.props('rows').length, '单个删除后行应减少').toBe(0) wrapper.unmount() }) it('多语言面板:批量删除选中多行通过 update:rows 上报且不弹弹窗', async () => { const wrapper = mount(ModuleI18nPanel, { props: { rows: [], languages: [ { code: 'zh-CN', name: '简体中文', default: true }, { code: 'en-US', name: 'English', default: false }, ], loading: false, }, attachTo: document.body, }) await settle() for (let i = 0; i < 2; i++) { await clickToolbarAdd(wrapper, '新增多语言') await syncRows(wrapper) } expect(wrapper.props('rows').length).toBe(2) await selectRowCheckbox(wrapper, 0) await selectRowCheckbox(wrapper, 1) await clickToolbarBatch(wrapper) await syncRows(wrapper) await checkNoModal() expect(wrapper.props('rows').length, '批量删除后应无行').toBe(0) wrapper.unmount() }) })