import { describe, expect, it } from 'vitest'; import { AnimationState, type GameState } from '../../types'; import { applyWorldMutationsToGameState, resolveWorldMutations } from './worldMutationRouter'; const state = { worldType: null, customWorldProfile: null, playerCharacter: null, runtimeStats: { playTimeMs: 0, lastPlayTickAt: null, hostileNpcsDefeated: 0, questsAccepted: 0, itemsUsed: 0, scenesTraveled: 0, }, currentScene: 'Story', storyHistory: [], storyEngineMemory: { discoveredFactIds: [], inferredFactIds: [], activeThreadIds: ['thread-1'], resolvedScarIds: [], recentCarrierIds: [], recentSignalIds: [], recentCompanionReactions: [], currentChapter: null, currentJourneyBeatId: null, companionArcStates: [], worldMutations: [], chronicle: [], factionTensionStates: [], currentCampEvent: null, currentSetpieceDirective: null, continueGameDigest: null, }, chapterState: null, characterChats: {}, animationState: AnimationState.IDLE, currentEncounter: null, npcInteractionActive: false, currentScenePreset: { id: 'scene-1', name: '断桥旧哨', description: '旧哨火和断桥一起守着边城北口。', imageSrc: '', }, sceneHostileNpcs: [], playerX: 0, playerOffsetY: 0, playerFacing: 'right', playerActionMode: 'idle', scrollWorld: false, inBattle: false, playerHp: 0, playerMaxHp: 0, playerMana: 0, playerMaxMana: 0, 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, } satisfies GameState; describe('worldMutationRouter', () => { it('builds and applies scene mutation state', () => { const mutations = resolveWorldMutations({ state, signals: [ { id: 'signal-1', signalType: 'obtain_carrier', carrierId: 'carrier-1', threadIds: ['thread-1'], }, ], chapterState: { id: 'chapter-1', title: '封桥旧案·高潮', theme: '封桥旧案', primaryThreadIds: ['thread-1'], stage: 'climax', chapterSummary: '旧案被逼到台前。', }, }); const nextState = applyWorldMutationsToGameState({ state, mutations }); expect(mutations.length).toBeGreaterThan(0); expect(nextState.currentScenePreset?.mutationStateText).toBeTruthy(); }); });