Files
workspace/code/fms/fms-vue/tests/unit/module-rule-utils.spec.js
T
2026-09-17 21:29:08 +08:00

157 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 删除规则配置工具(module-management/ruleUtils):
* 关系业务键拼串/还原、predicate 三态推断、识别文案、新增行构造、条件面板 items 构造。
*/
import { describe, expect, it } from 'vitest'
import {
REF_RULE_HINT,
buildRuleQueryItems,
createRefRuleRow,
createRuleRow,
isCompleteRelationKey,
itemMapOf,
parseRelationScopeId,
parseRulePredicate,
relationScopeId,
ruleLabel,
ruleSummary,
ruleTypeText,
} from '@/views/module/module-management/ruleUtils'
const relation = {
b_source_module_id: 'order',
b_source_field: 'b_id',
b_target_module_id: 'order_item',
b_target_field: 'b_order_id',
}
const fields = [
{ b_field: 'b_status', b_name: '状态', b_type: 'select', b_canuse: 1 },
{ b_field: 'b_amount', b_name: '金额', b_type: 'money', b_canuse: 1 },
{ b_field: 'b_off', b_name: '停用字段', b_type: 'input', b_canuse: 0 },
]
describe('删除规则工具', () => {
it('关系业务键与四列互逆', () => {
expect(relationScopeId(relation)).toBe('order|b_id|order_item|b_order_id')
expect(parseRelationScopeId('order|b_id|order_item|b_order_id')).toEqual({
sourceModuleId: 'order',
sourceField: 'b_id',
targetModuleId: 'order_item',
targetField: 'b_order_id',
})
expect(isCompleteRelationKey(relation)).toBe(true)
expect(isCompleteRelationKey({ ...relation, b_target_field: null })).toBe(false)
})
it('predicate 三态:空=引用、JSON=勾条件、其余=SQL(非法 JSON 降级为 SQL)', () => {
expect(parseRulePredicate({ b_predicate: null }).kind).toBe('reference')
expect(parseRulePredicate({ b_predicate: ' ' }).kind).toBe('reference')
const dsl = parseRulePredicate({
b_predicate: JSON.stringify({
kind: 'dsl',
expr: { type: 'group', children: [{ type: 'condition', field: 'b_status' }] },
}),
})
expect(dsl.kind).toBe('dsl')
expect(dsl.expr.children).toHaveLength(1)
expect(parseRulePredicate({ b_predicate: 'select 1 where b_id in (:ids)' })).toMatchObject({
kind: 'sql',
})
expect(parseRulePredicate({ b_predicate: '{不是合法 JSON' })).toMatchObject({ kind: 'sql' })
// JSON 合法但不是 dsl 形状:按 SQL 文本处理,内容不丢
expect(parseRulePredicate({ b_predicate: '{"foo":1}' })).toMatchObject({ kind: 'sql' })
})
it('类型文案与摘要:条件走中文描述、SQL 单行截断、引用固定说明', () => {
const itemByField = itemMapOf(buildRuleQueryItems(fields, {}))
const dslRow = {
b_predicate: JSON.stringify({
kind: 'dsl',
expr: {
type: 'group',
children: [{ type: 'condition', field: 'b_amount', operator: 'gt', value: 0 }],
},
}),
}
expect(ruleTypeText(dslRow)).toBe('条件')
expect(ruleSummary(dslRow, itemByField)).toBe('金额 大于 0')
const sqlRow = { b_predicate: 'select\n b_id\nfrom bill where b_settled = 1' }
expect(ruleTypeText(sqlRow)).toBe('SQL')
expect(ruleSummary(sqlRow, itemByField)).toBe('select b_id from bill where b_settled = 1')
const refRow = { b_predicate: null }
expect(ruleTypeText(refRow)).toBe('引用')
expect(ruleSummary(refRow, itemByField)).toBe(REF_RULE_HINT)
})
it('识别文案:勾条件显示条件摘要,写 SQL 显示提示文案(缺文案退回 SQL 片段)', () => {
const itemByField = itemMapOf(buildRuleQueryItems(fields, {}))
const dslRow = {
b_predicate: JSON.stringify({
kind: 'dsl',
expr: {
type: 'group',
children: [{ type: 'condition', field: 'b_status', operator: 'eq', value: 'audit' }],
},
}),
}
expect(ruleLabel(dslRow, itemByField)).toBe('状态 等于 audit')
const sqlRow = { b_predicate: 'select 1 as b_id', b_message: '单据已销账,不能删除' }
expect(ruleLabel(sqlRow, itemByField)).toBe('单据已销账,不能删除')
expect(ruleLabel({ ...sqlRow, b_message: null }, itemByField)).toBe('select 1 as b_id')
expect(ruleLabel({ b_predicate: null }, itemByField)).toBe(REF_RULE_HINT)
})
it('新增行:主键由调用方取号传入,无名称/编码字段', () => {
const rule = createRuleRow('order', { id: '1900000000000000001', xh: 30 })
expect(rule).toMatchObject({
b_id: '1900000000000000001',
b_scope_type: 'module',
b_scope_id: 'order',
b_hook: 'delete.pre',
b_predicate: null,
b_canuse: 1,
b_xh: 30,
})
expect(rule.b_code).toBeUndefined()
expect(rule.b_name).toBeUndefined()
const ref = createRefRuleRow('order|b_id|order_item|b_order_id', '1900000000000000002')
expect(ref).toMatchObject({
b_id: '1900000000000000002',
b_scope_type: 'relation',
b_scope_id: 'order|b_id|order_item|b_order_id',
b_predicate: null,
b_hook: 'delete.pre',
})
})
it('items 构造:只列启用字段,类型映射控件,select 缺选项时降级为输入', () => {
const items = buildRuleQueryItems(fields, {
groups: [
{
conditions: [
{ field: 'b_status', operator: 'in', component: 'select', options: [{ value: 'a' }] },
],
},
],
})
expect(items.map((item) => item.field.b_field)).toEqual(['b_status', 'b_amount'])
// 查询配置里定义过:沿用其操作符/控件/选项
expect(items[0].config).toMatchObject({ b_operator: 'in', b_component: 'select' })
expect(items[0].options).toEqual([{ value: 'a', label: 'a' }])
// 未定义过:按字段类型推导(金额 → 数字输入)
expect(items[1].config.b_component).toBe('number')
expect(items[1].config.b_operator).toBe('eq')
})
})