import { describe, it, expect } from 'vitest'; import { XpCalculator } from '@domain/services/XpCalculator'; import { xpForLevel } from '@domain/value-objects/XpTable'; import { timeToGain } from '@domain/services/GaugeCalculator'; describe('Regression: XP timer display (v1.1.4 bug)', () => { const calc = new XpCalculator(); it('should NOT show ~23h for level 1→5 with tier 2 mangeoire', () => { const r = calc.computeEta({ currentLevel: 1, target: 5, gaugeLevels: { mangeoire: 50000 }, activeGauges: ['mangeoire'], }); // XP needed: xpForLevel(5) - xpForLevel(1) = 161 - 0 = 161 // timeToGain(50000, 161): tier2 zone (10000 pts at rate 20) → ceil(161/20)*10 = 90 sec expect(r.seconds).toBe(90); expect(r.seconds).toBeLessThan(3600); // Must be under 1h, NOT 23h }); it('should NOT show ~23h for level 1→10 with tier 1 mangeoire', () => { const r = calc.computeEta({ currentLevel: 1, target: 10, gaugeLevels: { mangeoire: 30000 }, activeGauges: ['mangeoire'], }); // XP needed: xpForLevel(10) - xpForLevel(1) = 809 // timeToGain(30000, 809): tier1 zone → ceil(809/10)*10 = 810 sec expect(r.seconds).toBe(810); expect(r.seconds).toBeLessThan(3600); }); it('XP model uses depleting gauge (same as other stats)', () => { // Bug fix: XP uses gainedIn/timeToGain (depleting gauge), NOT a fixed rate. // The gauge depletes from 70000 → 0 giving decreasing XP per tick. // Real scenario: gauge 70000, level 1→67, xpNeeded = 67942 const xpNeeded = xpForLevel(67) - xpForLevel(1); // 67942 const sec = timeToGain(70000, xpNeeded); // Tier2 (70000→40000): 30000pts at rate20 = 15000sec // Tier1 (40000→2058): 37942pts at rate10 = 37950sec // Total: 52950sec ≈ 14h42m expect(sec).toBe(52950); expect(sec).toBeLessThan(200000); }); it('returns Infinity when gauge cannot provide enough XP without recharge', () => { // Gauge 50000 = 50000 total pts. Level 1→100 needs 172668 XP → impossible without recharge. const xpNeeded = xpForLevel(100) - xpForLevel(1); // 172668 const sec = timeToGain(50000, xpNeeded); expect(sec).toBe(Infinity); }); });