diff --git a/game-runtime/src/adapter/adapter.test.mjs b/game-runtime/src/adapter/adapter.test.mjs index 8e5b356d..7d65421d 100644 --- a/game-runtime/src/adapter/adapter.test.mjs +++ b/game-runtime/src/adapter/adapter.test.mjs @@ -214,3 +214,46 @@ test('控制类:paddle 对齐下落球 → 接住计分', () => { for (let i = 0; i < 30; i++) game.update(0.1); // 推进至球落到 paddle 层 assert.ok(game._forensicsView().state().score >= 1, '对齐后应接住至少 1 次'); }); + +// ── 鲁棒性:便宜模型产的 gameDefinition 常残缺/畸形,生产路适配器须优雅降级不崩 ── +test('鲁棒:空 gameDefinition → 不崩、phase playing、可渲染', () => { + const game = adaptGameDefinition({})(); + const { boot, g } = makeBoot(); + game.init(boot); + assert.equal(game._forensicsView().state().phase, 'playing'); + assert.doesNotThrow(() => { game.update(0.016); game.render(g); }); + assert.ok(g._rec.fillRects.length >= 1, '至少画背景'); +}); + +test('鲁棒:实体缺 transform / 组件引用不存在 → 默认值不崩', () => { + const src = { gameDefinition: { entities: [{ id: 'x', components: ['nope'] }], scenes: [{ id: 's', entityRefs: ['x'] }], rules: [] } }; + const game = adaptGameDefinition(src)(); + const { boot, g } = makeBoot(); + game.init(boot); + assert.equal(typeof game._forensicsView().state().targets[0].x, 'number'); + assert.doesNotThrow(() => game.render(g)); +}); + +test('鲁棒:畸形 rule condition → 不触发不崩', () => { + const src = { gameDefinition: { entities: [], scenes: [], rules: [{ id: 'r', condition: '乱七八糟', outcome: 'win' }] }, config: {} }; + const game = adaptGameDefinition(src)(); + const { boot } = makeBoot(); + game.init(boot); + game.update(0.016); + assert.equal(game._forensicsView().state().phase, 'playing'); // 畸形条件不误触发 win +}); + +test('鲁棒:不支持的 behavior op → 忽略不崩', () => { + const src = { gameDefinition: { entities: [], scenes: [], rules: [], behaviors: [{ id: 'b', trigger: 'input', op: 'unknown-op' }] }, config: {} }; + const game = adaptGameDefinition(src)(); + const { boot, inputBridge } = makeBoot(); + game.init(boot); + assert.doesNotThrow(() => inputBridge._emit('pointerdown', { x: 100, y: 100 })); + assert.equal(game._forensicsView().state().score, 0); +}); + +test('鲁棒:render/update 在 init 前调 → 不崩(防御阶段错)', () => { + const game = adaptGameDefinition(SOURCE)(); + const { g } = makeBoot(); + assert.doesNotThrow(() => { game.update(0.016); game.render(g); }); +});