fix: resolve all TypeScript compilation errors
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m17s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m17s
- Fixed DisciplinesAttunementType enum usage in discipline data files - Fixed EquipmentSlot import in equipment/types.ts - Fixed enchantment-effects.ts export/import chain - Fixed safe-persist.ts StateStorage type compatibility - Fixed store persist partial return types for all stores - Fixed gameStore.ts ElementState type and error handling - Fixed useGameDerived.ts missing properties on GameCoordinatorStore - Added SkillUpgradeChoice type to types.ts - Fixed ActionButtons.tsx optional currentStudyTarget prop - Fixed GameToast.tsx Toast type compatibility - Fixed EnchantmentDesigner sub-component type mismatches - Fixed SpireCombatPage equippedInstances/equipmentInstances types - Fixed page.tsx computeClickMana argument - Added baseCastTime to SpellDef type - Fixed golem/types.ts and loot-drops.ts import paths - Fixed craftingStore.ts missing lastError in initial state and actions - Fixed store-actions-combat-prestige.test.ts Memory type usage - Fixed floor-utils.upgraded.test.ts array type annotation - Fixed computed-stats.test.ts state type assertions - Fixed activity-log.test.ts state type annotation - Fixed discipline-math.test.ts enum value usage - Fixed game-loop.test.ts vitest mock import - Various other test file type fixes
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { addActivityLogEntry } from '../utils/activity-log';
|
||||
import type { ActivityLogEntry } from '../types';
|
||||
import type { ActivityEventType, ActivityLogEntry } from '../types';
|
||||
|
||||
// ─── addActivityLogEntry ──────────────────────────────────────────────────────
|
||||
|
||||
@@ -106,8 +106,8 @@ describe('addActivityLogEntry', () => {
|
||||
});
|
||||
|
||||
it('should handle various event types', () => {
|
||||
const state = { activityLog: [] };
|
||||
const types = ['combat', 'crafting', 'prestige', 'discovery', 'achievement'] as const;
|
||||
const state: { activityLog: ActivityLogEntry[] } = { activityLog: [] };
|
||||
const types: ActivityEventType[] = ['combat', 'damage_dealt', 'enemy_defeated', 'floor_cleared', 'spell_cast'];
|
||||
let current = state;
|
||||
for (const eventType of types) {
|
||||
const result = addActivityLogEntry(current, eventType, `Event: ${eventType}`);
|
||||
|
||||
@@ -164,7 +164,7 @@ describe('deductSpellCost', () => {
|
||||
describe('computeMaxMana', () => {
|
||||
it('should return base 100 with no skills or upgrades', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
skills: {} as Record<string, number>,
|
||||
prestigeUpgrades: {},
|
||||
skillUpgrades: {},
|
||||
skillTiers: {},
|
||||
@@ -176,7 +176,7 @@ describe('computeMaxMana', () => {
|
||||
|
||||
it('should include manaWell prestige upgrade', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
skills: {} as Record<string, number>,
|
||||
prestigeUpgrades: { manaWell: 5 },
|
||||
skillUpgrades: {},
|
||||
skillTiers: {},
|
||||
@@ -188,7 +188,7 @@ describe('computeMaxMana', () => {
|
||||
|
||||
it('should apply multiplier from effects', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
skills: {} as Record<string, number>,
|
||||
prestigeUpgrades: {},
|
||||
skillUpgrades: {},
|
||||
skillTiers: {},
|
||||
@@ -200,7 +200,7 @@ describe('computeMaxMana', () => {
|
||||
|
||||
it('should apply bonus from effects', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
skills: {} as Record<string, number>,
|
||||
prestigeUpgrades: {},
|
||||
skillUpgrades: {},
|
||||
skillTiers: {},
|
||||
@@ -214,14 +214,14 @@ describe('computeMaxMana', () => {
|
||||
describe('computeRegen', () => {
|
||||
it('should return base regen with no skills', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
prestigeUpgrades: {},
|
||||
skillUpgrades: {},
|
||||
skillTiers: {},
|
||||
attunements: {},
|
||||
skills: {} as Record<string, number>,
|
||||
prestigeUpgrades: {} as Record<string, number>,
|
||||
skillUpgrades: {} as Record<string, string[]>,
|
||||
skillTiers: {} as Record<string, number>,
|
||||
attunements: {} as Record<string, { active: boolean; level: number; experience: number }>,
|
||||
};
|
||||
const effects = { regenBonus: 0, regenMultiplier: 1, permanentRegenBonus: 0 } as any;
|
||||
const result = computeRegen(state, effects);
|
||||
const result = computeRegen(state as any, effects);
|
||||
// Base regen is 2 (this test provides effects, so no attunement bonus)
|
||||
expect(result).toBe(2);
|
||||
});
|
||||
@@ -230,10 +230,10 @@ describe('computeRegen', () => {
|
||||
describe('computeClickMana', () => {
|
||||
it('should return base click mana with no skills', () => {
|
||||
const state = {
|
||||
skills: {},
|
||||
skills: {} as Record<string, number>,
|
||||
};
|
||||
const discipline = { bonuses: {}, multipliers: {} };
|
||||
const result = computeClickMana(state, discipline);
|
||||
const result = computeClickMana(state.skills, discipline);
|
||||
expect(result).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
canEquipInSlot,
|
||||
isTwoHanded,
|
||||
} from '../crafting-utils';
|
||||
import type { EquipmentSlot } from '../types/equipmentSlot';
|
||||
|
||||
function makeInstance(overrides = {}): any {
|
||||
return {
|
||||
@@ -12,12 +13,15 @@ function makeInstance(overrides = {}): any {
|
||||
enchantments: [],
|
||||
totalCapacity: 100,
|
||||
usedCapacity: 0,
|
||||
rarity: 'common',
|
||||
quality: 100,
|
||||
tags: [],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('canEquipInSlot', () => {
|
||||
const baseSlot: Record<string, string | null> = {
|
||||
const baseSlot: Record<EquipmentSlot, string | null> = {
|
||||
head: null,
|
||||
body: null,
|
||||
hands: null,
|
||||
@@ -72,7 +76,7 @@ describe('canEquipInSlot', () => {
|
||||
});
|
||||
|
||||
it('should block two-handed weapon if mainHand is occupied', () => {
|
||||
const slot = { ...baseSlot, mainHand: 'something' };
|
||||
const slot: Record<EquipmentSlot, string | null> = { ...baseSlot, mainHand: 'something' };
|
||||
const instance = makeInstance({ instanceId: 'th_1', typeId: 'oakStaff' });
|
||||
// Even if type is not two-handed, the slot check for mainHand+offHand applies
|
||||
const result = canEquipInSlot(instance, 'mainHand', slot, {});
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('checkRecipeMaterials', () => {
|
||||
});
|
||||
|
||||
it('should return canCraft false when materials are empty', () => {
|
||||
const result = checkRecipeMaterials(makeRecipe(), {});
|
||||
const result = checkRecipeMaterials(makeRecipe(), {} as any);
|
||||
expect(result.canCraft).toBe(false);
|
||||
expect(result.missingMaterials).toEqual({ manaCrystalDust: 5, arcaneShard: 2 });
|
||||
});
|
||||
@@ -52,8 +52,8 @@ describe('checkRecipeMaterials', () => {
|
||||
});
|
||||
|
||||
it('should handle recipe with no materials', () => {
|
||||
const emptyRecipe = makeRecipe({});
|
||||
const result = checkRecipeMaterials(emptyRecipe, {});
|
||||
const emptyRecipe = makeRecipe({} as any);
|
||||
const result = checkRecipeMaterials(emptyRecipe, {} as any);
|
||||
expect(result.canCraft).toBe(true);
|
||||
expect(result.missingMaterials).toEqual({});
|
||||
});
|
||||
@@ -89,7 +89,7 @@ describe('deductRecipeMaterials', () => {
|
||||
});
|
||||
|
||||
it('should handle empty materials', () => {
|
||||
const result = deductRecipeMaterials(makeRecipe(), {});
|
||||
const result = deductRecipeMaterials(makeRecipe(), {} as any);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
@@ -129,13 +129,13 @@ describe('refundCraftMaterials', () => {
|
||||
it('should floor fractional refunds', () => {
|
||||
// Recipe with manaCrystalDust: 7
|
||||
// 50% of 7 = 3.5 → floor = 3
|
||||
const recipeWithOdd = makeRecipe({ manaCrystalDust: 7 });
|
||||
const recipeWithOdd = makeRecipe({ manaCrystalDust: 7 } as any);
|
||||
const result = refundCraftMaterials(recipeWithOdd, 0.5);
|
||||
expect(result.manaCrystalDust).toBe(3);
|
||||
});
|
||||
|
||||
it('should handle empty recipe materials', () => {
|
||||
const emptyRecipe = makeRecipe({});
|
||||
const emptyRecipe = makeRecipe({} as any);
|
||||
const result = refundCraftMaterials(emptyRecipe);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getUnlockedPerks,
|
||||
calculateDisciplineStats,
|
||||
} from '../utils/discipline-math';
|
||||
import { DisciplinesAttunementType } from '../types/disciplines';
|
||||
import type { DisciplineDefinition, DisciplineState } from '../types/disciplines';
|
||||
|
||||
// ─── Test Fixtures ────────────────────────────────────────────────────────────
|
||||
@@ -15,7 +16,7 @@ import type { DisciplineDefinition, DisciplineState } from '../types/disciplines
|
||||
const rawMastery: DisciplineDefinition = {
|
||||
id: 'raw-mastery',
|
||||
name: 'Raw Mana Mastery',
|
||||
attunement: 'base',
|
||||
attunement: DisciplinesAttunementType.BASE,
|
||||
manaType: 'raw',
|
||||
baseCost: 5,
|
||||
description: 'Learn to harness raw mana more efficiently.',
|
||||
@@ -44,7 +45,7 @@ const rawMastery: DisciplineDefinition = {
|
||||
const elementalAttunement: DisciplineDefinition = {
|
||||
id: 'elemental-attunement',
|
||||
name: 'Elemental Attunement',
|
||||
attunement: 'base',
|
||||
attunement: DisciplinesAttunementType.BASE,
|
||||
manaType: 'fire',
|
||||
baseCost: 10,
|
||||
description: 'Begin focusing raw mana into fire.',
|
||||
@@ -66,7 +67,7 @@ const elementalAttunement: DisciplineDefinition = {
|
||||
const cappedPerkDiscipline: DisciplineDefinition = {
|
||||
id: 'capped-test',
|
||||
name: 'Capped Perk Test',
|
||||
attunement: 'base',
|
||||
attunement: DisciplinesAttunementType.BASE,
|
||||
manaType: 'raw',
|
||||
baseCost: 1,
|
||||
description: 'Test discipline with capped perk.',
|
||||
|
||||
@@ -128,7 +128,8 @@ describe('getFloorElement - Enhanced Edge Cases', () => {
|
||||
});
|
||||
|
||||
it('should handle negative floors', () => {
|
||||
expect(getFloorElement(-10)).toBe('water'); // (-10-1) % 7 = -11 % 7 = 3, earth? Check actual formula
|
||||
// ((-10-1) % 7 + 7) % 7 = (-11 % 7 + 7) % 7 = (-4 + 7) % 7 = 3 => earth
|
||||
expect(getFloorElement(-10)).toBe('earth' as string);
|
||||
});
|
||||
|
||||
it('should return only valid element names', () => {
|
||||
@@ -141,7 +142,7 @@ describe('getFloorElement - Enhanced Edge Cases', () => {
|
||||
|
||||
it('should maintain consistent cycling for sequential calls', () => {
|
||||
// Ensure the cycle is consistent across multiple calls
|
||||
const elements = [];
|
||||
const elements: string[] = [];
|
||||
for (let i = 1; i <= 21; i++) {
|
||||
elements.push(getFloorElement(i));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ import { describe, it, expect } from 'vitest';
|
||||
import { generateFloorState } from '../utils/room-utils';
|
||||
import { PUZZLE_ROOMS, SWARM_CONFIG, SPEED_ROOM_CONFIG } from '../constants';
|
||||
import { getGuardianForFloor } from '../data/guardian-encounters';
|
||||
import { getFloorMaxHP, getDodgeChance } from '../utils/floor-utils';
|
||||
import { getFloorMaxHP } from '../utils/floor-utils';
|
||||
import { getDodgeChance } from '../utils/room-utils';
|
||||
|
||||
// ─── generateFloorState ───────────────────────────────────────────────────────
|
||||
|
||||
@@ -72,8 +73,8 @@ describe('generateFloorState', () => {
|
||||
Math.random = () => 0.19;
|
||||
const state = generateFloorState(7);
|
||||
expect(state.roomType).toBe('puzzle');
|
||||
expect(state.puzzleAttunements.length).toBeGreaterThan(0);
|
||||
expect(typeof state.puzzleAttunements[0]).toBe('string');
|
||||
expect(state.puzzleAttunements!.length).toBeGreaterThan(0);
|
||||
expect(typeof state.puzzleAttunements![0]).toBe('string');
|
||||
Math.random = originalRandom;
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ function resetCombatStore() {
|
||||
currentAction: 'meditate',
|
||||
castProgress: 0,
|
||||
spireMode: false,
|
||||
currentRoom: { roomType: 'combat', enemies: [], cleared: false },
|
||||
currentRoom: { roomType: 'combat', enemies: [] },
|
||||
clearedFloors: {},
|
||||
climbDirection: null,
|
||||
isDescending: false,
|
||||
@@ -222,32 +222,32 @@ describe('PrestigeStore', () => {
|
||||
|
||||
describe('addMemory / removeMemory', () => {
|
||||
it('should add a memory when slots available', () => {
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3, tier: 1, upgrades: [] });
|
||||
expect(usePrestigeStore.getState().memories.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not add duplicate memory', () => {
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 5 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3, tier: 1, upgrades: [] });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 5, tier: 1, upgrades: [] });
|
||||
expect(usePrestigeStore.getState().memories.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not exceed memory slots', () => {
|
||||
usePrestigeStore.setState({ memorySlots: 1 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 1 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaSpring', level: 1 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 1, tier: 1, upgrades: [] });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaSpring', level: 1, tier: 1, upgrades: [] });
|
||||
expect(usePrestigeStore.getState().memories.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should remove memory by skillId', () => {
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 3, tier: 1, upgrades: [] });
|
||||
usePrestigeStore.getState().removeMemory('manaFlow');
|
||||
expect(usePrestigeStore.getState().memories.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should clear all memories', () => {
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 1 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaSpring', level: 1 });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaFlow', level: 1, tier: 1, upgrades: [] });
|
||||
usePrestigeStore.getState().addMemory({ skillId: 'manaSpring', level: 1, tier: 1, upgrades: [] });
|
||||
usePrestigeStore.getState().clearMemories();
|
||||
expect(usePrestigeStore.getState().memories.length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ function resetCombatStore() {
|
||||
currentAction: 'meditate',
|
||||
castProgress: 0,
|
||||
spireMode: false,
|
||||
currentRoom: { roomType: 'combat', enemies: [], cleared: false },
|
||||
currentRoom: { roomType: 'combat', enemies: [] },
|
||||
clearedFloors: {},
|
||||
climbDirection: null,
|
||||
isDescending: false,
|
||||
|
||||
@@ -42,7 +42,7 @@ function resetAllStores() {
|
||||
currentAction: 'meditate',
|
||||
castProgress: 0,
|
||||
spireMode: false,
|
||||
currentRoom: { roomType: 'combat', enemies: [], cleared: false },
|
||||
currentRoom: { roomType: 'combat', enemies: [] },
|
||||
clearedFloors: {},
|
||||
climbDirection: null,
|
||||
isDescending: false,
|
||||
|
||||
Reference in New Issue
Block a user