import { ConfigMgr, MapJsonLoader } from '@data/ConfigMgr'; import { LevelMgr } from '@logic/LevelMgr'; import { cameraFromLevel } from '@logic/CameraScroller'; import { EnemyType } from '@data/Interfaces'; // Reuse delivered JSON. import enemies from '../../assets/resources/configs/enemies.json'; import items from '../../assets/resources/configs/items.json'; import weapons from '../../assets/resources/configs/weapons.json'; import levels from '../../assets/resources/configs/levels.json'; import bosses from '../../assets/resources/configs/bosses.json'; import stories from '../../assets/resources/configs/stories.json'; async function loadBundle() { const mgr = new ConfigMgr( new MapJsonLoader({ 'configs/enemies': enemies, 'configs/items': items, 'configs/weapons': weapons, 'configs/levels': levels, 'configs/bosses': bosses, 'configs/stories': stories, }) ); await mgr.load(); return mgr; } describe('Chapter-1 levels — JSON × LevelMgr integration (task 7.2)', () => { it('exposes all 5 levels (1-1 … 1-5)', async () => { const mgr = await loadBundle(); for (const id of ['1-1', '1-2', '1-3', '1-4', '1-5']) { expect(mgr.level(id)).toBeDefined(); } }); it('1-1 requires killing 3 妖坊 within 75s (req 8.1)', async () => { const mgr = await loadBundle(); const lv = mgr.level('1-1'); expect(lv.timeLimitSec).toBe(75); expect(lv.objective).toEqual({ kind: 'kill_count', enemy: EnemyType.YaoFang, count: 3 }); }); it('1-3 is a bi-directional cave stage with 10 青忍 objective (req 8.3)', async () => { const mgr = await loadBundle(); const lv = mgr.level('1-3'); expect(lv.scrollDirection).toBe('horizontal_bi'); expect(lv.objective).toEqual({ kind: 'kill_count', enemy: EnemyType.QingRen, count: 10 }); }); it('1-4 is a vertical castle-wall stage with reach_top objective (req 8.4)', async () => { const mgr = await loadBundle(); const lv = mgr.level('1-4'); expect(lv.scrollDirection).toBe('vertical'); expect(lv.objective).toEqual({ kind: 'reach_top' }); }); it('1-5 is a defeat-boss objective pointing at 双幻坊 (req 8.5)', async () => { const mgr = await loadBundle(); const lv = mgr.level('1-5'); expect(lv.objective.kind).toBe('defeat_boss'); expect(lv.objective.bossId).toBe('shuang_huan_fang'); }); it('CameraScroller instantiates cleanly from each chapter-1 level', async () => { const mgr = await loadBundle(); for (const id of ['1-1', '1-2', '1-3', '1-4', '1-5']) { const cam = cameraFromLevel(mgr.level(id)); expect(cam.offsetX).toBe(0); expect(cam.offsetY).toBe(0); } }); it('LevelMgr drives every level to victory via its configured objective', async () => { const mgr = await loadBundle(); for (const id of ['1-1', '1-2', '1-3', '1-4', '1-5']) { const lv = new LevelMgr(mgr.level(id)); switch (lv.level.objective.kind) { case 'kill_count': for (let k = 0; k < (lv.level.objective.count ?? 0); k++) { lv.onEnemyKilled(lv.level.objective.enemy!); } break; case 'reach_top': lv.onReachedTop(); break; case 'defeat_boss': lv.onBossKilled(); break; } expect(lv.tick(0.016)).toBe('victory'); } }); });