133 lines
4.7 KiB
JavaScript
133 lines
4.7 KiB
JavaScript
/**
|
|
* 删除 SQL 规则面板(module-management/ModuleRulePanel):
|
|
* - 加载回填只补界面派生列(_rowKey / _labelText),业务列不变(不置脏);
|
|
* - 列表识别:优先提示文案,缺文案退回 SQL 片段;
|
|
* - 保存前校验:必须有主键、SQL 含 :ids 且为只读查询、必须填提示文案;
|
|
* - 新增规则:取号后打开弹窗,确定时才落草稿。
|
|
*/
|
|
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { mount, 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'
|
|
import { IDS_PLACEHOLDER } from '@/views/module/module-management/ruleUtils'
|
|
|
|
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
|
|
},
|
|
})
|
|
})
|
|
|
|
/** 库中已有的一条删除 SQL 规则 */
|
|
const sqlRow = {
|
|
b_id: '1900000000000000001',
|
|
b_module_id: 'order',
|
|
b_sql: `select b_id from bill where b_id in (${IDS_PLACEHOLDER}) and b_settled = 1`,
|
|
b_message: '单据已销账,不能删除',
|
|
b_canuse: 1,
|
|
b_xh: 10,
|
|
}
|
|
|
|
async function mountPanel({ rules = [] } = {}) {
|
|
const pinia = createPinia()
|
|
setActivePinia(pinia)
|
|
const wrapper = mount(ModuleRulePanel, {
|
|
props: {
|
|
moduleId: 'order',
|
|
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('删除 SQL 规则面板', () => {
|
|
it('加载回填只补界面派生列,业务列不变', async () => {
|
|
const wrapper = await mountPanel({ rules: [{ ...sqlRow }] })
|
|
const next = lastRules(wrapper)
|
|
|
|
expect(next).toHaveLength(1)
|
|
expect(next[0]._rowKey).toBeTruthy()
|
|
expect(next[0]._labelText).toBe('单据已销账,不能删除')
|
|
// 剥掉 _ 前缀的内部键后与库中行完全一致(不置脏)
|
|
expect(stripInternalKeys(next[0])).toEqual(sqlRow)
|
|
})
|
|
|
|
it('识别文案:缺提示文案时退回 SQL 片段', async () => {
|
|
const wrapper = await mountPanel({
|
|
rules: [{ ...sqlRow, b_message: null }],
|
|
})
|
|
const next = lastRules(wrapper)
|
|
|
|
expect(next[0]._labelText).toContain('select b_id from bill')
|
|
})
|
|
|
|
it('校验:主键、:ids 标记、只读查询、提示文案都要满足', async () => {
|
|
const noId = { ...sqlRow, b_id: '' }
|
|
const noPlaceholder = { ...sqlRow, b_id: '1900000000000000002', b_sql: 'select b_id from bill' }
|
|
const notReadOnly = {
|
|
...sqlRow,
|
|
b_id: '1900000000000000003',
|
|
b_sql: `delete from bill where b_id in (${IDS_PLACEHOLDER})`,
|
|
}
|
|
const noMessage = {
|
|
...sqlRow,
|
|
b_id: '1900000000000000004',
|
|
b_message: '',
|
|
}
|
|
const wrapper = await mountPanel({ rules: [noId, noPlaceholder, notReadOnly, noMessage] })
|
|
const errors = wrapper.vm.validate()
|
|
|
|
expect(errors).toContain('第 1 条规则:缺少主键(请重新新增)')
|
|
expect(errors).toContain('第 2 条规则:规则 SQL 必须包含 :ids 标记')
|
|
expect(errors).toContain('第 3 条规则:规则 SQL 必须是只读查询(以 select 或 with 开头)')
|
|
expect(errors).toContain('第 4 条规则:请填写提示文案')
|
|
})
|
|
|
|
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.editingRow.b_module_id).toBe('order')
|
|
expect(wrapper.vm.ruleModalOpen).toBe(true)
|
|
// 未确定前不进列表
|
|
expect(lastRules(wrapper)).toBe(null)
|
|
|
|
wrapper.vm.onRuleOk({ ...wrapper.vm.editingRow, b_sql: 'select 1 as b_id' })
|
|
await nextTick()
|
|
expect(lastRules(wrapper)).toHaveLength(1)
|
|
expect(lastRules(wrapper)[0].b_id).toBe('1900000000000000009')
|
|
})
|
|
})
|