Files
workspace/code/g3soft-erp/web/tests/views/module/module-management/ModuleAutoCodePanel.spec.ts
T
2026-10-14 22:24:12 +08:00

132 lines
5.2 KiB
TypeScript
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.
/**
* 自动编码面板(s_autocode):惰性建行 + 实时预览 + 校验。
*
* 关键点:模块从未配置自动编码时草稿保持空数组(打开面板即建行会把「无变更」
* diff 成一条 insert),只有用户首次操作才落行;且 defineModel 写入后不能立刻
* 回读 prop(要下一轮才回传),所以建行后返回的是 reactive 代理行。
*/
import { describe, expect, it } from 'vitest'
import { mount } from '@vue/test-utils'
import { G3Switch } from '@g3soft/ui'
import ModuleAutoCodePanel from '@/views/module/module-management/ModuleAutoCodePanel.vue'
import type { ModuleAutoCodeRow } from '@/views/module/module-management/utils'
const FIELDS = [
{ b_field: 'b_id', b_name: '编码', b_type: 'input', b_canuse: 1 },
{ b_field: 'b_no', b_name: '业务单号', b_type: 'input', b_canuse: 1 },
{ b_field: 'b_bz', b_name: '备注', b_type: 'textarea', 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 },
]
/** 造一行规则:只写关心的字段,其余取启用态的常用默认值 */
function row(overrides: Partial<ModuleAutoCodeRow> = {}): ModuleAutoCodeRow {
return {
b_module_id: 'm1',
b_field: 'b_no',
b_prefix: '',
b_dateformat: 'yyyyMM',
b_separator: '-',
b_seqwidth: 5,
b_resettype: 'month',
b_startvalue: 1,
b_currentperiod: null,
b_currentvalue: 0,
b_canuse: 1,
...overrides,
}
}
/** 模拟父级 v-model:autocode:emit 回来要显式写回 prop,否则复现不了「立刻回读旧值」的问题 */
function mountPanel(autocode: ModuleAutoCodeRow[] = []) {
const wrapper = mount(ModuleAutoCodePanel, {
props: {
moduleId: 'm1',
fields: FIELDS,
autocode,
'onUpdate:autocode': (value: ModuleAutoCodeRow[]) => wrapper.setProps({ autocode: value }),
},
})
return wrapper
}
describe('自动编码面板', () => {
it('首次拨「启用」时惰性建行并写回 b_canuse(defineModel 不能写完立刻回读)', async () => {
const wrapper = mountPanel()
// 模块从未配置自动编码:草稿为空,此时拨开关会走 ensureRow 建行
wrapper.findComponent(G3Switch).vm.$emit('update:modelValue', true)
await wrapper.vm.$nextTick()
const emitted = wrapper.emitted('update:autocode')
expect(emitted).toBeTruthy()
const created = emitted![0][0] as ModuleAutoCodeRow[]
expect(created[0].b_canuse).toBe(1)
expect(created[0].b_module_id).toBe('m1')
// 业务编号字段自动取第一个可用文本字段(排除主键 b_id、非文本类型与停用字段)
expect(created[0].b_field).toBe('b_no')
})
it('已有一行时就地改,不再新建也不重新 emit 整个数组', async () => {
// 传进去的数组即父级持有的草稿:断言它被就地改写
const draft = [row({ b_canuse: 0, b_prefix: 'A' })]
const wrapper = mountPanel(draft)
wrapper.findComponent(G3Switch).vm.$emit('update:modelValue', true)
await wrapper.vm.$nextTick()
// 已落草稿:直接改这一行的属性(父级 ref 是深度响应式,改得见)
expect(wrapper.emitted('update:autocode')).toBeUndefined()
expect(draft[0]?.b_canuse).toBe(1)
expect(draft[0]?.b_prefix).toBe('A') // 沿用原行,未被占位行覆盖
})
it('紧凑网格固定竖排且标签左对齐,不跟随全局横排配置', () => {
const wrapper = mountPanel()
expect(wrapper.find('form').classes()).toContain('g3-form--vertical')
// 标签左对齐依赖 G3Form 的默认 labelAlign=left;竖排下若回到 right 会被推到整列右边缘
expect(wrapper.findAll('.g3-form-item__label.is-label-right')).toHaveLength(0)
})
it('预览按 前缀 + 日期 + 补位流水号 拼接', async () => {
const wrapper = mountPanel([
row({ b_prefix: 'G3', b_dateformat: '', b_seqwidth: 4, b_resettype: 'none' }),
])
await wrapper.vm.$nextTick()
const preview = wrapper.find('[data-field="b_preview"] input')
expect(preview.attributes('readonly')).toBeDefined()
expect((preview.element as HTMLInputElement).value).toBe('G3-0001')
})
it('启用态下的合法规则校验通过', async () => {
const wrapper = mountPanel([row()])
expect(await wrapper.vm.validate()).toEqual([])
})
it('启用但未选业务编号字段时报错(错误挂在对应 FormItem 上)', async () => {
const wrapper = mountPanel([row({ b_field: null })])
const errors = await wrapper.vm.validate()
expect(errors.map((item) => item.name)).toContain('b_field')
expect(errors.find((item) => item.name === 'b_field')?.errors[0]).toBe('请选择业务编号字段')
})
it('位数超出 1-18 时报错', async () => {
const wrapper = mountPanel([row({ b_seqwidth: 20 })])
const errors = await wrapper.vm.validate()
expect(errors.find((item) => item.name === 'b_seqwidth')?.errors[0]).toBe(
'流水号位数必须是 1 到 18 之间的整数',
)
})
it('未启用时不校验(占位行只用于展示)', async () => {
const wrapper = mountPanel()
expect(await wrapper.vm.validate()).toEqual([])
})
})