20260917212907
This commit is contained in:
1 parent
6fa3d8535e
commit
5cbf745bbf
115 files changed
+4104
-85
No files matched your search
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* 删除规则面板(module-management/ModuleRulePanel):
|
||||
* - 加载回填只补界面派生列(_rowKey / _typeText / _labelText),业务列不变(不置脏);
|
||||
* - 列表识别:勾条件显示条件中文摘要,写 SQL 显示提示文案;
|
||||
* - 保存前校验:勾条件要有条件、写 SQL 要有 SQL 与提示文案;
|
||||
* - 其他模块在本模块上配的引用规则只读展示,可跳转到源模块。
|
||||
*/
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { nextTick } from 'vue'
|
||||
import ModuleRulePanel from '@/views/module/module-management/ModuleRulePanel.vue'
|
||||
import { stripInternalKeys } from '@/utils/dataChanges'
|
||||
|
||||
vi.mock('@/services/api', () => ({
|
||||
loadDataApi: vi.fn(),
|
||||
nextIdApi: vi.fn(() => Promise.resolve({ data: '1900000000000000009', code: 0 })),
|
||||
}))
|
||||
|
||||
vi.mock('@/components/ui/message/message-manager.js', () => {
|
||||
const m = { success: vi.fn(), error: vi.fn(), warning: vi.fn(), info: vi.fn() }
|
||||
return { Message: m, default: m }
|
||||
})
|
||||
|
||||
// jsdom 无布局:StkTable 在 clientWidth 为 0 时启用虚拟列裁剪,补成宽容器
|
||||
beforeAll(() => {
|
||||
Object.defineProperty(HTMLElement.prototype, 'clientWidth', {
|
||||
configurable: true,
|
||||
get() {
|
||||
return 5000
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const FIELDS = [
|
||||
{ b_field: 'b_status', b_name: '状态', b_type: 'select', b_canuse: 1 },
|
||||
{ b_field: 'b_settled', b_name: '已销账', b_type: 'checkbox', b_canuse: 1 },
|
||||
]
|
||||
|
||||
const MODULES = [
|
||||
{ b_id: 'order', b_name: '订单', b_canuse: 1 },
|
||||
{ b_id: 'order_item', b_name: '订单明细', b_canuse: 1 },
|
||||
]
|
||||
|
||||
/** 库中已有的一条勾条件规则:状态等于 audit */
|
||||
const dslRow = {
|
||||
b_id: '1900000000000000001',
|
||||
b_scope_type: 'module',
|
||||
b_scope_id: 'order',
|
||||
b_hook: 'delete.pre',
|
||||
b_predicate: JSON.stringify({
|
||||
kind: 'dsl',
|
||||
expr: {
|
||||
type: 'group',
|
||||
children: [
|
||||
{ type: 'condition', field: 'b_status', operator: 'eq', value: 'audit', join: 'and' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
b_message: null,
|
||||
b_canuse: 1,
|
||||
b_xh: 10,
|
||||
}
|
||||
|
||||
async function mountPanel({ rules = [], refRulesReverse = [] } = {}) {
|
||||
const pinia = createPinia()
|
||||
pinia.install({ provide() {}, config: { globalProperties: {} } })
|
||||
setActivePinia(pinia)
|
||||
const wrapper = mount(ModuleRulePanel, {
|
||||
props: {
|
||||
moduleId: 'order',
|
||||
fields: FIELDS,
|
||||
querySchema: {},
|
||||
refRulesReverse,
|
||||
modules: MODULES,
|
||||
loading: false,
|
||||
modelValue: rules,
|
||||
},
|
||||
global: { plugins: [pinia] },
|
||||
attachTo: document.body,
|
||||
})
|
||||
await flushPromises()
|
||||
await nextTick()
|
||||
return wrapper
|
||||
}
|
||||
|
||||
const lastRules = (wrapper) => {
|
||||
const events = wrapper.emitted('update:modelValue') || []
|
||||
return events.length ? events[events.length - 1][0] : null
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
describe('删除规则面板', () => {
|
||||
it('加载回填只补界面派生列,业务列不变', async () => {
|
||||
const wrapper = await mountPanel({ rules: [{ ...dslRow }] })
|
||||
const next = lastRules(wrapper)
|
||||
|
||||
expect(next).toHaveLength(1)
|
||||
expect(next[0]._rowKey).toBeTruthy()
|
||||
expect(next[0]._typeText).toBe('条件')
|
||||
expect(next[0]._labelText).toBe('状态 等于 audit')
|
||||
// 剥掉 _ 前缀的内部键后与库中行完全一致(不置脏)
|
||||
expect(stripInternalKeys(next[0])).toEqual(dslRow)
|
||||
})
|
||||
|
||||
it('识别文案:写 SQL 的规则用提示文案当列表文案', async () => {
|
||||
const sqlRow = {
|
||||
...dslRow,
|
||||
b_id: '1900000000000000002',
|
||||
b_predicate: 'select b_id from bill where b_settled = 1',
|
||||
b_message: '单据已销账,不能删除',
|
||||
}
|
||||
const wrapper = await mountPanel({ rules: [sqlRow] })
|
||||
const next = lastRules(wrapper)
|
||||
|
||||
expect(next[0]._typeText).toBe('SQL')
|
||||
expect(next[0]._labelText).toBe('单据已销账,不能删除')
|
||||
})
|
||||
|
||||
it('校验:勾条件必须真有条件,写 SQL 必须有 SQL 与提示文案', async () => {
|
||||
const emptyDsl = {
|
||||
...dslRow,
|
||||
b_id: '1900000000000000003',
|
||||
b_predicate: JSON.stringify({ kind: 'dsl', expr: { type: 'group', children: [] } }),
|
||||
}
|
||||
const sqlWithoutMessage = {
|
||||
...dslRow,
|
||||
b_id: '1900000000000000004',
|
||||
b_predicate: 'select b_id from bill where b_id in (:ids)',
|
||||
b_message: '',
|
||||
}
|
||||
const wrapper = await mountPanel({ rules: [emptyDsl, sqlWithoutMessage] })
|
||||
const errors = wrapper.vm.validate()
|
||||
|
||||
expect(errors).toContain('第 1 条规则:至少配置一个判定条件')
|
||||
expect(errors).toContain('第 2 条规则:写 SQL 的规则必须填写提示文案')
|
||||
|
||||
// 引用规则不该出现在模块级列表里;没有主键的行也要拦住(新增取号失败的情况)
|
||||
const refWrapper = await mountPanel({ rules: [{ ...dslRow, b_predicate: null }] })
|
||||
expect(refWrapper.vm.validate()).toContain('第 1 条规则:引用规则请到「模块关联」面板维护')
|
||||
const noIdWrapper = await mountPanel({ rules: [{ ...dslRow, b_id: '' }] })
|
||||
expect(noIdWrapper.vm.validate()).toContain('第 1 条规则:缺少主键(请重新新增)')
|
||||
})
|
||||
|
||||
it('新增规则:取号后打开弹窗,确定时才落草稿', async () => {
|
||||
const wrapper = await mountPanel()
|
||||
await wrapper.vm.openRuleModal(null)
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.vm.editingIsNew).toBe(true)
|
||||
expect(wrapper.vm.editingRow.b_id).toBe('1900000000000000009')
|
||||
expect(wrapper.vm.ruleModalOpen).toBe(true)
|
||||
// 未确定前不进列表
|
||||
expect(lastRules(wrapper)).toBe(null)
|
||||
|
||||
wrapper.vm.onRuleOk({ ...wrapper.vm.editingRow, b_predicate: 'select 1 as b_id' })
|
||||
await nextTick()
|
||||
expect(lastRules(wrapper)).toHaveLength(1)
|
||||
expect(lastRules(wrapper)[0].b_id).toBe('1900000000000000009')
|
||||
})
|
||||
|
||||
it('只读区:把引用规则还原成模块名/字段列,并支持跳转到源模块', async () => {
|
||||
const wrapper = await mountPanel({
|
||||
refRulesReverse: [
|
||||
{
|
||||
b_id: '1900000000000000005',
|
||||
b_scope_type: 'relation',
|
||||
b_scope_id: 'order_item|b_order_id|order|b_id',
|
||||
b_hook: 'delete.pre',
|
||||
b_predicate: null,
|
||||
b_canuse: 1,
|
||||
b_xh: 10,
|
||||
},
|
||||
],
|
||||
})
|
||||
await nextTick()
|
||||
|
||||
expect(wrapper.text()).toContain('其他模块在本模块上配置的引用规则')
|
||||
expect(wrapper.text()).toContain('订单明细(order_item)')
|
||||
expect(wrapper.text()).toContain('订单(order)')
|
||||
|
||||
const viewButton = wrapper.findAll('button').find((button) => button.text().includes('查看'))
|
||||
expect(viewButton, '只读区应有查看按钮').toBeTruthy()
|
||||
await viewButton.trigger('click')
|
||||
expect(wrapper.emitted('navigate')?.[0]).toEqual(['order_item'])
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user