import { describe, it, expect, beforeEach } from 'vitest'; import { ProgressionManager } from '../ProgressionManager'; import { type CombatantActor } from '../../core/types'; describe('ProgressionManager', () => { let progressionManager: ProgressionManager; let mockPlayer: CombatantActor; beforeEach(() => { progressionManager = new ProgressionManager(); mockPlayer = { id: 1, category: 'combatant', isPlayer: true, pos: { x: 0, y: 0 }, speed: 100, stats: { maxHp: 20, hp: 20, level: 1, exp: 0, expToNextLevel: 100, statPoints: 5, skillPoints: 2, strength: 10, dexterity: 10, intelligence: 10, attack: 5, defense: 2, critChance: 5, critMultiplier: 150, accuracy: 90, lifesteal: 0, evasion: 5, blockChance: 0, luck: 0, passiveNodes: [] } } as any; }); it('should allocate strength and increase maxHp and attack', () => { progressionManager.allocateStat(mockPlayer, 'strength'); expect(mockPlayer.stats.strength).toBe(11); expect(mockPlayer.stats.maxHp).toBe(22); expect(mockPlayer.stats.hp).toBe(22); expect(mockPlayer.stats.attack).toBeCloseTo(5.2); expect(mockPlayer.stats.statPoints).toBe(4); }); it('should allocate dexterity and increase speed', () => { progressionManager.allocateStat(mockPlayer, 'dexterity'); expect(mockPlayer.stats.dexterity).toBe(11); expect(mockPlayer.speed).toBe(101); expect(mockPlayer.stats.statPoints).toBe(4); }); it('should allocate intelligence and increase defense every 5 points', () => { // Current INT is 10 (multiple of 5) // Next multiple is 15 progressionManager.allocateStat(mockPlayer, 'intelligence'); expect(mockPlayer.stats.intelligence).toBe(11); expect(mockPlayer.stats.defense).toBe(2); // No increase yet mockPlayer.stats.intelligence = 14; mockPlayer.stats.statPoints = 1; progressionManager.allocateStat(mockPlayer, 'intelligence'); expect(mockPlayer.stats.intelligence).toBe(15); expect(mockPlayer.stats.defense).toBe(3); // Increased! }); it('should not allocate stats if statPoints are 0', () => { mockPlayer.stats.statPoints = 0; progressionManager.allocateStat(mockPlayer, 'strength'); expect(mockPlayer.stats.strength).toBe(10); }); it('should apply passive node bonuses', () => { progressionManager.allocatePassive(mockPlayer, 'off_1'); expect(mockPlayer.stats.attack).toBe(7); expect(mockPlayer.stats.skillPoints).toBe(1); expect(mockPlayer.stats.passiveNodes).toContain('off_1'); progressionManager.allocatePassive(mockPlayer, 'util_2'); expect(mockPlayer.stats.expToNextLevel).toBe(90); expect(mockPlayer.stats.skillPoints).toBe(0); }); it('should not apply the same passive twice', () => { progressionManager.allocatePassive(mockPlayer, 'off_1'); const pointsAfterFirst = mockPlayer.stats.skillPoints; progressionManager.allocatePassive(mockPlayer, 'off_1'); expect(mockPlayer.stats.skillPoints).toBe(pointsAfterFirst); expect(mockPlayer.stats.attack).toBe(7); // Same as before }); });