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(); } }); });