20260911173133

This commit is contained in:
oneao committed 2026-09-11 17:31:34 +08:00
1 parent 3838ed74b1
commit f3ad727f1c
60 files changed
+4971 -6621

No files matched your search

@@ -1,5 +1,5 @@
/**
* i18n 统一维护纯函数测试:
* i18n 统一维护纯函数测试(V2:(b_key, b_locale) 复合键):
* 覆盖 index.vue 上移后的受管键收集、扁平行→透视、reconcile(补齐/跟名/失效清理)与保存 diff,
* 守护「ModuleI18nPanel 受控化」后数据编排逻辑不回退。
*/
@@ -17,10 +17,10 @@ const languages = [
]
const defaultLocale = 'zh-CN'
// V2:b_id 即模块编码
function demoModule(over = {}) {
return {
b_id: '9',
b_code: 'demo',
b_id: 'demo',
b_module_type: 'data',
b_name: '演示模块',
b_i18n: null,
@@ -28,12 +28,16 @@ function demoModule(over = {}) {
}
}
function demoField(over = {}) {
return { b_field: 'name', b_name: '姓名', b_i18n: null, ...over }
}
describe('collectManagedI18nItems 受管键收集', () => {
it('收集模块名与字段名的受管键', () => {
const items = collectManagedI18nItems({
module: demoModule(),
fields: [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }],
groups: [],
fields: [demoField()],
schemas: [],
})
expect(items.map((i) => i.key)).toEqual(['module.demo', 'field.demo.name'])
expect(items[0].id).toBe('module:module.demo')
@@ -42,11 +46,33 @@ describe('collectManagedI18nItems 受管键收集', () => {
expect(items[1].defaultValue).toBe('姓名')
})
it('收集界面配置分组标题的受管键', () => {
const items = collectManagedI18nItems({
module: demoModule(),
fields: [],
schemas: [
{
schemaVersion: 1,
children: [
{
type: 'group',
title: '基础信息',
i18n: 'group.demo.basic',
children: [],
},
],
},
],
})
expect(items.map((i) => i.key)).toContain('group.demo.basic')
expect(items.find((i) => i.key === 'group.demo.basic').defaultValue).toBe('基础信息')
})
it('模块编码为空时不产出受管键(新建未填编码)', () => {
const items = collectManagedI18nItems({
module: demoModule({ b_code: '' }),
fields: [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }],
groups: [],
module: demoModule({ b_id: '' }),
fields: [demoField()],
schemas: [],
})
expect(items).toEqual([])
})
@@ -54,12 +80,12 @@ describe('collectManagedI18nItems 受管键收集', () => {
describe('buildI18nPivot / reconcileI18nRows', () => {
it('扁平行转透视后 reconcile 补齐受管行并跟随默认语言', () => {
const flat = [{ b_id: '100', b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' }]
const flat = [{ b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' }]
const pivot = buildI18nPivot(flat)
const items = collectManagedI18nItems({
module: demoModule(),
fields: [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }],
groups: [],
fields: [demoField()],
schemas: [],
})
const rows = reconcileI18nRows(pivot, items, { defaultLocale, languages })
@@ -74,20 +100,18 @@ describe('buildI18nPivot / reconcileI18nRows', () => {
})
it('名称变化后 reconcile 自动跟名,人工翻译不被覆盖', () => {
const fields = [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }]
const flat = [{ b_id: '100', b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' }]
const flat = [{ b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' }]
let rows = reconcileI18nRows(
buildI18nPivot(flat),
collectManagedI18nItems({ module: demoModule(), fields, groups: [] }),
collectManagedI18nItems({ module: demoModule(), fields: [demoField()], schemas: [] }),
{ defaultLocale, languages },
)
// 改名后再次 reconcile
rows = reconcileI18nRows(
rows,
collectManagedI18nItems({
module: demoModule({ b_name: '演示模块V2' }),
fields: [{ ...fields[0], b_name: '姓名V2' }],
groups: [],
fields: [demoField({ b_name: '姓名V2' })],
schemas: [],
}),
{ defaultLocale, languages },
)
@@ -98,8 +122,11 @@ describe('buildI18nPivot / reconcileI18nRows', () => {
})
it('字段删除后:无翻译的自动补齐行被清理,带翻译的保留为普通行', () => {
const field = { b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }
const items = collectManagedI18nItems({ module: demoModule(), fields: [field], groups: [] })
const items = collectManagedI18nItems({
module: demoModule(),
fields: [demoField()],
schemas: [],
})
const rows = reconcileI18nRows(buildI18nPivot([]), items, { defaultLocale, languages })
expect(rows.some((r) => r._managedId === 'field:field.demo.name')).toBe(true)
@@ -111,14 +138,14 @@ describe('buildI18nPivot / reconcileI18nRows', () => {
describe('buildI18nChangeRequest 保存 diff', () => {
const originalFlat = [
{ b_id: '100', b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' },
{ b_key: 'field.demo.name', b_locale: 'en-US', b_value: 'Name' },
]
function draftRows() {
const items = collectManagedI18nItems({
module: demoModule(),
fields: [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }],
groups: [],
fields: [demoField()],
schemas: [],
})
return reconcileI18nRows(buildI18nPivot(originalFlat), items, { defaultLocale, languages })
}
@@ -127,40 +154,43 @@ describe('buildI18nChangeRequest 保存 diff', () => {
const req = buildI18nChangeRequest({
draftRows: draftRows(),
originalFlat,
moduleId: '9',
languages,
})
expect(req).not.toBeNull()
expect(req.key_field).toBe('b_key,b_locale')
const keys = (req.inserts || []).map((r) => `${r.b_key}|${r.b_locale}`).sort()
expect(keys).toEqual(['field.demo.name|zh-CN', 'module.demo|zh-CN'])
// 新增行 b_id 为负数临时 id(保存编排统一换真实主键)
expect((req.inserts || []).every((r) => /^-\d+$/.test(String(r.b_id)))).toBe(true)
// en-US 有主键且未变化 → 不产生 update
// en-US 未变化 → 不产生 update
expect(req.updates || []).toHaveLength(0)
})
it('修改语言值只产生对应 cell 的 update', () => {
it('修改语言值只产生对应 cell 的 update(按 b_key + b_locale 定位)', () => {
const rows = draftRows()
rows.find((r) => r.b_key === 'field.demo.name')['en-US'] = 'NewName'
const req = buildI18nChangeRequest({
draftRows: rows,
originalFlat,
moduleId: '9',
languages,
})
expect(req.updates.some((r) => r.b_id === '100' && r.b_value === 'NewName')).toBe(true)
expect(
req.updates.some(
(r) => r.b_key === 'field.demo.name' && r.b_locale === 'en-US' && r.b_value === 'NewName',
),
).toBe(true)
// 复合主键定位,不再依赖 b_id
expect((req.updates || []).every((r) => r.b_id === undefined)).toBe(true)
})
it('与基线完全一致时不产生请求', () => {
const originalAll = [
...originalFlat,
{ b_id: '101', b_key: 'module.demo', b_locale: 'zh-CN', b_value: '演示模块' },
{ b_id: '102', b_key: 'field.demo.name', b_locale: 'zh-CN', b_value: '姓名' },
{ b_key: 'module.demo', b_locale: 'zh-CN', b_value: '演示模块' },
{ b_key: 'field.demo.name', b_locale: 'zh-CN', b_value: '姓名' },
]
const items = collectManagedI18nItems({
module: demoModule(),
fields: [{ b_id: '1', b_field: 'name', b_name: '姓名', b_i18n: null }],
groups: [],
fields: [demoField()],
schemas: [],
})
const rows = reconcileI18nRows(buildI18nPivot(originalAll), items, {
defaultLocale,
@@ -169,7 +199,6 @@ describe('buildI18nChangeRequest 保存 diff', () => {
const req = buildI18nChangeRequest({
draftRows: rows,
originalFlat: originalAll,
moduleId: '9',
languages,
})
expect(req).toBeNull()