This commit is contained in:
97
src/data/hostileNpcPresets.test.ts
Normal file
97
src/data/hostileNpcPresets.test.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import {describe, expect, it, vi} from 'vitest';
|
||||
|
||||
import type {GameState} from '../types';
|
||||
import {AnimationState, WorldType} from '../types';
|
||||
import {rollHostileNpcLoot} from './hostileNpcPresets';
|
||||
|
||||
function createGameState(): GameState {
|
||||
return {
|
||||
worldType: WorldType.WUXIA,
|
||||
customWorldProfile: null,
|
||||
playerCharacter: null,
|
||||
runtimeStats: {
|
||||
playTimeMs: 0,
|
||||
lastPlayTickAt: null,
|
||||
hostileNpcsDefeated: 0,
|
||||
questsAccepted: 0,
|
||||
itemsUsed: 0,
|
||||
scenesTraveled: 0,
|
||||
},
|
||||
currentScene: 'Story',
|
||||
storyHistory: [],
|
||||
characterChats: {},
|
||||
animationState: AnimationState.IDLE,
|
||||
currentEncounter: null,
|
||||
npcInteractionActive: false,
|
||||
currentScenePreset: {
|
||||
id: 'ruins',
|
||||
name: '断碑古道',
|
||||
description: '阴气与碎骨混在旧路之间。',
|
||||
imageSrc: '/ruins.png',
|
||||
npcs: [],
|
||||
treasureHints: [],
|
||||
},
|
||||
sceneHostileNpcs: [],
|
||||
playerX: 0,
|
||||
playerOffsetY: 0,
|
||||
playerFacing: 'right',
|
||||
playerActionMode: 'idle',
|
||||
scrollWorld: false,
|
||||
inBattle: false,
|
||||
playerHp: 100,
|
||||
playerMaxHp: 100,
|
||||
playerMana: 60,
|
||||
playerMaxMana: 60,
|
||||
playerSkillCooldowns: {},
|
||||
activeBuildBuffs: [],
|
||||
activeCombatEffects: [],
|
||||
playerCurrency: 0,
|
||||
playerInventory: [],
|
||||
playerEquipment: {
|
||||
weapon: null,
|
||||
armor: null,
|
||||
relic: null,
|
||||
},
|
||||
npcStates: {},
|
||||
quests: [],
|
||||
roster: [],
|
||||
companions: [],
|
||||
currentBattleNpcId: null,
|
||||
currentNpcBattleMode: null,
|
||||
currentNpcBattleOutcome: null,
|
||||
sparReturnEncounter: null,
|
||||
sparPlayerHpBefore: null,
|
||||
sparPlayerMaxHpBefore: null,
|
||||
sparStoryHistoryBefore: null,
|
||||
};
|
||||
}
|
||||
|
||||
describe('hostileNpcPresets', () => {
|
||||
it('combines preset loot with runtime semantic drops', async () => {
|
||||
const randomSpy = vi.spyOn(Math, 'random').mockReturnValue(0);
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn().mockRejectedValue(new TypeError('network disabled in test')),
|
||||
);
|
||||
|
||||
try {
|
||||
const loot = await rollHostileNpcLoot(createGameState(), [
|
||||
{
|
||||
id: 'monster-03',
|
||||
name: '断骨祟灵',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(loot.some(item => item.id === 'monster-loot:bone-dust')).toBe(true);
|
||||
expect(
|
||||
loot.some(item => item.runtimeMetadata?.generationChannel === 'monster_drop'),
|
||||
).toBe(true);
|
||||
expect(
|
||||
loot.find(item => item.id === 'monster-loot:bone-dust')?.runtimeMetadata?.storyFingerprint,
|
||||
).toBeTruthy();
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
randomSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user