test: add cross-module integration tests for tick pipeline
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m22s

Add 38 integration tests split across 4 files (all under 400 lines):
- cross-module-helpers.ts: shared resetAllStores() and tickN() utilities
- cross-module-combat-meditation.test.ts (12 tests): combat floor
  clearing, meditation regen flow, incursion effects, convert action
- cross-module-prestige-discipline.test.ts (15 tests): prestige loop
  reset, discipline mana drain/XP, pact ritual completion
- cross-module-lifecycle-consistency.test.ts (11 tests): full loop
  lifecycle, store consistency invariants, pause/gameOver blocking

All 38 new + 112 existing tests pass.
This commit is contained in:
2026-05-25 18:26:32 +02:00
parent fdf3984e75
commit 4aa12a10f0
7 changed files with 617 additions and 3 deletions
@@ -0,0 +1,114 @@
import { useGameStore } from '../stores/gameStore';
import { useManaStore, makeInitialElements } from '../stores/manaStore';
import { useCombatStore, makeInitialSpells } from '../stores/combatStore';
import { usePrestigeStore } from '../stores/prestigeStore';
import { useUIStore } from '../stores/uiStore';
import { useDisciplineStore } from '../stores/discipline-slice';
import { useAttunementStore } from '../stores/attunementStore';
import { useCraftingStore } from '../stores/craftingStore';
import { getFloorMaxHP } from '../utils';
export function resetAllStores() {
useUIStore.setState({
paused: false,
gameOver: false,
victory: false,
logs: [],
});
useGameStore.setState({
day: 1,
hour: 0,
incursionStrength: 0,
containmentWards: 0,
initialized: true,
});
useManaStore.setState({
rawMana: 100,
meditateTicks: 0,
totalManaGathered: 0,
elements: makeInitialElements(50, {}),
});
useCombatStore.setState({
currentFloor: 1,
floorHP: getFloorMaxHP(1),
floorMaxHP: getFloorMaxHP(1),
maxFloorReached: 1,
activeSpell: 'manaBolt',
currentAction: 'meditate',
castProgress: 0,
spireMode: false,
currentRoom: { roomType: 'combat', enemies: [] },
clearedFloors: {},
climbDirection: null,
isDescending: false,
golemancy: { enabledGolems: [], summonedGolems: [], lastSummonFloor: 0 },
equipmentSpellStates: [],
comboHitCount: 0,
floorHitCount: 0,
spells: makeInitialSpells(),
activityLog: [],
achievements: { unlocked: [], progress: {} },
totalSpellsCast: 0,
totalDamageDealt: 0,
totalCraftsCompleted: 0,
});
usePrestigeStore.setState({
loopCount: 0,
insight: 0,
totalInsight: 0,
loopInsight: 0,
prestigeUpgrades: {},
pactSlots: 1,
defeatedGuardians: [],
signedPacts: [],
signedPactDetails: {},
pactRitualFloor: null,
pactRitualProgress: 0,
});
useDisciplineStore.setState({
disciplines: {},
activeIds: [],
concurrentLimit: 1,
totalXP: 0,
processedPerks: [],
});
useAttunementStore.setState({
attunements: {},
});
useCraftingStore.setState({
designProgress: null,
designProgress2: null,
preparationProgress: null,
applicationProgress: null,
equipmentCraftingProgress: null,
enchantmentDesigns: [],
unlockedEffects: [],
equippedInstances: {},
equipmentInstances: {},
lootInventory: {
materials: {},
blueprints: [],
},
enchantmentSelection: {
selectedEquipmentType: null,
selectedEffects: [],
designName: '',
selectedDesign: null,
selectedEquipmentInstance: null,
},
lastError: null,
});
}
export function tickN(n: number) {
for (let i = 0; i < n; i++) {
useGameStore.getState().tick();
}
}