95 lines
3.6 KiB
TypeScript
95 lines
3.6 KiB
TypeScript
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');
|
||
}
|
||
});
|
||
});
|