// 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); // 钉住精确数量(与 test_constants.js 同一个数):松下界删掉整个 View 都还能通过 t.eq('真实精灵数量', Object.keys(realIndex).length, 378); process.exit(t.done('spriteindex') ? 0 : 1);