布局配置按键名引用精灵,本模块把嵌套的精灵常量展平供查。 重复键与未知键一律抛错——静默覆盖会让界面指向别处的精灵且极难排查。 用例含真实常量的全量建索引校验。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
3.9 KiB
JavaScript
88 lines
3.9 KiB
JavaScript
// View → group → 精灵 的常量树 → 扁平键名索引
|
||
const { load, throws } = require('./_load');
|
||
const t = require('./_assert')();
|
||
|
||
load('client/js/01_SubGame/codes/core/SpriteIndex.js');
|
||
|
||
// ---- 展平:Layer 与 group 的 id 都不进索引,精灵进 ----
|
||
const tree = {
|
||
TopInfoView: {
|
||
Layer: 101,
|
||
TopInfo: { id: 201, BTN_A: 1001, BTN_B: 1002 }
|
||
},
|
||
PlayerMarkView: {
|
||
Layer: 101,
|
||
LeftMark: { id: 202, P_LEFT_BANKER: 1100 },
|
||
RightMark: { id: 203, P_RIGHT_BANKER: 1110 }
|
||
}
|
||
};
|
||
t.eq('展平结果', EQW_SpriteIndex.build(tree),
|
||
{ BTN_A: 1001, BTN_B: 1002, P_LEFT_BANKER: 1100, P_RIGHT_BANKER: 1110 });
|
||
|
||
// ---- Layer 与 group 的 id 不进索引 ----
|
||
const flat = EQW_SpriteIndex.build(tree);
|
||
t.eq('Layer 不进索引', flat.Layer, undefined);
|
||
t.eq('group 的 id 不进索引', flat.id, undefined);
|
||
|
||
// ---- 群组映射:精灵 → 它所属的群组 ID ----
|
||
t.eq('群组映射', EQW_SpriteIndex.buildGroupMap(tree),
|
||
{ BTN_A: 201, BTN_B: 201, P_LEFT_BANKER: 202, P_RIGHT_BANKER: 203 });
|
||
|
||
// ---- 反面:一个 View 恰好一个 Layer;Layer1/Layer2 这种多图层写法要报错 ----
|
||
// (跨图层的界面应拆成两个 View,各带自己的 Layer——一个 View 将来对应一个 BaseComponent)
|
||
const multiLayer = {
|
||
OverlayView: { Layer1: 104, Layer2: 105, Bar: { id: 230, TIP_BG: 1750 } }
|
||
};
|
||
t.eq('多 Layer 写法报错', throws(() => EQW_SpriteIndex.build(multiLayer)), true);
|
||
|
||
// ---- 反面:View 缺 Layer 声明要报错 ----
|
||
const noLayer = { ViewA: { G1: { id: 201, BTN: 1001 } } };
|
||
t.eq('View 缺 Layer 报错', throws(() => EQW_SpriteIndex.build(noLayer)), true);
|
||
|
||
// ---- 反面:重复键报错,不静默覆盖 ----
|
||
const dupTree = {
|
||
ViewA: { Layer: 101, G1: { id: 201, SAME: 1001 } },
|
||
ViewB: { Layer: 102, G2: { id: 202, SAME: 1002 } }
|
||
};
|
||
t.eq('重复键报错', throws(() => EQW_SpriteIndex.build(dupTree)), true);
|
||
|
||
// ---- 反面:精灵值不是数字要报错 ----
|
||
const badValue = { ViewA: { Layer: 101, G1: { id: 201, NESTED: { x: 1 } } } };
|
||
t.eq('精灵值非数字报错', throws(() => EQW_SpriteIndex.build(badValue)), true);
|
||
|
||
// ---- 反面:View 下混入标量键(不是 group 容器)要报错 ----
|
||
// 例如把群组 ID 误写成 View 级的 `Group: 201`,而不是包进 group 容器
|
||
const strayScalar = { ViewA: { Layer: 101, Group: 201, G1: { id: 202, BTN: 1001 } } };
|
||
t.eq('View 下混入标量键报错', throws(() => EQW_SpriteIndex.build(strayScalar)), true);
|
||
|
||
// ---- 反面:group 容器缺 id 要报错 ----
|
||
const noGroupId = { ViewA: { Layer: 101, G1: { BTN: 1001 } } };
|
||
t.eq('group 缺 id 报错', throws(() => EQW_SpriteIndex.build(noGroupId)), true);
|
||
|
||
// ---- idOf / groupIdOf:查得到 / 查不到抛错 ----
|
||
EQW_SpriteIndex.init(tree);
|
||
t.eq('idOf 查到', EQW_SpriteIndex.idOf('BTN_A'), 1001);
|
||
t.eq('groupIdOf 查到', EQW_SpriteIndex.groupIdOf('P_RIGHT_BANKER'), 203);
|
||
t.eq('idOf 查不到抛错', throws(() => EQW_SpriteIndex.idOf('NOT_EXIST')), true);
|
||
t.eq('groupIdOf 查不到抛错', throws(() => EQW_SpriteIndex.groupIdOf('NOT_EXIST')), true);
|
||
|
||
// ---- 空树 ----
|
||
t.eq('空树', EQW_SpriteIndex.build({}), {});
|
||
|
||
// ---- 真实常量:EQW_Sprites 能完整建索引且无重复键 ----
|
||
load('client/js/01_SubGame/codes/config/Layers.js');
|
||
load('client/js/01_SubGame/codes/config/Groups.js');
|
||
load('client/js/01_SubGame/codes/config/Sprites_Table.js');
|
||
load('client/js/01_SubGame/codes/config/Sprites_Cards.js');
|
||
load('client/js/01_SubGame/codes/config/Sprites_Action.js');
|
||
load('client/js/01_SubGame/codes/config/Sprites_Result.js');
|
||
load('client/js/01_SubGame/codes/config/Sprites_CreateRoom.js');
|
||
|
||
let realOk = true;
|
||
let realIndex = {};
|
||
try { realIndex = EQW_SpriteIndex.build(EQW_Sprites); } catch (e) { realOk = false; console.log('建索引失败: ' + e.message); }
|
||
t.eq('真实精灵常量无重复键', realOk, true);
|
||
t.eq('真实精灵数量 > 200', Object.keys(realIndex).length > 200, true);
|
||
|
||
process.exit(t.done('spriteindex') ? 0 : 1);
|