Files
KateLegend2_proj/tests/logic/Chapter1Levels.test.ts
T
2026-05-06 08:17:32 +08:00

95 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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');
}
});
});