20260917165839

This commit is contained in:
oneao committed 2026-09-17 16:58:40 +08:00
1 parent 182ed86966
commit 38e1e66c3b
108 files changed
+2497 -1215

No files matched your search

@@ -0,0 +1,138 @@
/**
* 查询配置面板回写语义(module-management):
* - query 行草稿与 query JSON 不是一一映射(缺省 component/quick/groups、运行时写入的
* area 等),只加载(含保存后同模块重载、schema ref 换新对象)不得回写,
* 否则草稿与库中基线文本不一致 → 切树节点误报「未保存」,并静默改写未建模属性;
* - 用户真实编辑(改操作符/组件/默认值、增删行)必须回写;
* - 回写保留编辑器未建模的条件属性(如 area)。
*/
import { beforeAll, beforeEach, describe, expect, it } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { nextTick } from 'vue'
import ModuleQueryConfigPanel from '@/views/module/module-management/ModuleQueryConfigPanel.vue'
// jsdom 无布局:StkTable 在 clientWidth 为 0 时启用虚拟列裁剪,补成宽容器
beforeAll(() => {
Object.defineProperty(HTMLElement.prototype, 'clientWidth', {
configurable: true,
get() {
return 5000
},
})
})
/** 库中历史查询配置:缺 quick 键、条件未显式写 component,且带运行时写入的 area */
const legacySchema = {
schemaVersion: 1,
groups: [
{
logic: 'and',
conditions: [
{ field: 'b_name', operator: 'like', area: 'hidden' },
{ field: 'b_amount', operator: 'eq', component: 'number' },
],
},
],
}
const fields = [
{ b_field: 'b_name', b_name: '名称', b_type: 'input', b_canuse: 1 },
{ b_field: 'b_amount', b_name: '金额', b_type: 'money', b_canuse: 1 },
]
async function mountPanel(modelValue) {
const pinia = createPinia()
pinia.install({ provide() {}, config: { globalProperties: {} } })
setActivePinia(pinia)
const wrapper = mount(ModuleQueryConfigPanel, {
props: { moduleId: 'demo', fields, modelValue, loading: false },
global: { plugins: [pinia] },
attachTo: document.body,
})
await nextTick()
return wrapper
}
const lastSchema = (wrapper) => {
const events = wrapper.emitted('update:modelValue') || []
return events.length ? events[events.length - 1][0] : null
}
beforeEach(() => {
document.body.innerHTML = ''
})
describe('查询配置面板:加载不回写、编辑才回写', () => {
it('仅加载(schema 换新对象)不回写草稿', async () => {
const wrapper = await mountPanel(legacySchema)
expect(lastSchema(wrapper)).toBe(null)
// 模拟父级重载:同一份历史 JSON 以新引用下发(与 parseSchema 后的重载一致)
await wrapper.setProps({ modelValue: JSON.parse(JSON.stringify(legacySchema)) })
await nextTick()
expect(lastSchema(wrapper)).toBe(null)
// 再模拟一次:父级下发的已是规范化 JSON,同样不得回写
await wrapper.setProps({
modelValue: {
schemaVersion: 1,
quick: [],
groups: [
{
logic: 'and',
conditions: [
{ field: 'b_name', operator: 'like', component: 'input', area: 'hidden' },
{ field: 'b_amount', operator: 'eq', component: 'number' },
],
},
],
},
})
await nextTick()
expect(lastSchema(wrapper)).toBe(null)
})
it('用户编辑操作符时回写,并保留未建模的 area 属性与 quick', async () => {
const wrapper = await mountPanel({ ...legacySchema, quick: ['b_name'] })
wrapper.vm.queryConfig = wrapper.vm.queryConfig.map((row, index) =>
index === 0 ? { ...row, b_operator: 'eq' } : row,
)
await nextTick()
const next = lastSchema(wrapper)
expect(next).not.toBe(null)
expect(next.quick).toEqual(['b_name'])
expect(next.groups[0].conditions[0]).toEqual({
field: 'b_name',
operator: 'eq',
component: 'input',
area: 'hidden',
})
})
it('改字段后不复用原字段的扩展属性', async () => {
const wrapper = await mountPanel(legacySchema)
wrapper.vm.queryConfig = wrapper.vm.queryConfig.map((row, index) =>
index === 0 ? { ...row, b_field: 'b_amount', b_component: 'number', b_operator: 'eq' } : row,
)
await nextTick()
const next = lastSchema(wrapper)
expect(next.groups[0].conditions[0]).toEqual({
field: 'b_amount',
operator: 'eq',
component: 'number',
})
})
it('删除行后回写(条件为空 → groups 置空)', async () => {
const wrapper = await mountPanel(legacySchema)
wrapper.vm.queryConfig = []
await nextTick()
const next = lastSchema(wrapper)
expect(next.groups).toEqual([])
expect(next.quick).toEqual([])
})
})