import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { computeGaugeLive, enclosGlobalState } from '@presentation/helpers/gauge-live'; import { createEnclos } from '@domain/entities/Enclos'; import { createDragodinde } from '@domain/entities/Dragodinde'; import type { Enclos } from '@domain/entities/Enclos'; import type { Dragodinde } from '@domain/entities/Dragodinde'; /** * Régression : après une recharge de jauge en cours de timer, * le countdown (cntDown) doit être fini (pas Infinity). * * Scénario reproduit : la jauge baffeur se vide complètement, * le joueur la recharge → le countdown doit recalculer à partir * du nouveau niveau de jauge, pas rester bloqué à ∞. */ describe('Régression: countdown fini après recharge de jauge vidée', () => { const NOW = 1_700_000_000_000; // timestamp fixe beforeEach(() => { vi.useFakeTimers(); vi.setSystemTime(NOW); }); afterEach(() => { vi.useRealTimers(); }); function buildEnclos(dd: Dragodinde, opts: { startGl: number; elapsedSec: number; recharges?: { atSec: number; level: number }[]; currentGl: number; }): Enclos { const enc = createEnclos(1, 'Test'); enc.activeGauges = ['baffeur']; enc.gaugeLevels = { ...enc.gaugeLevels, baffeur: opts.currentGl }; enc.dragodindes = [dd]; enc.timer = { running: true, startTime: NOW - opts.elapsedSec * 1000, pausedAt: null, pausedMs: 0, snapGauges: { baffeur: opts.startGl }, snapStats: { [dd.id]: { serenite: 0, endurance: 0, maturite: 0, amour: 0, xp: 1 } }, gaugeRecharges: opts.recharges ? { baffeur: opts.recharges } : {}, }; return enc; } it('sans recharge et jauge vidée → cntDown est Infinity', () => { const dd = createDragodinde(1); // Jauge baffeur départ = 100, elapsed = 200s → largement vidée (100 pts = tier1 10/tick) // timeToGain(100, 100) = ceil(100/10)*10 = 100s → à 200s la jauge est à 0 const enc = buildEnclos(dd, { startGl: 100, elapsedSec: 200, currentGl: 0, }); const result = computeGaugeLive(enc, dd, 'baffeur', 200, true); expect(result.curGl).toBe(0); expect(result.cntDown).toBe(Infinity); }); it('après recharge de la jauge vidée → cntDown est fini et > 0', () => { const dd = createDragodinde(1); // Jauge baffeur départ = 100, elapsed = 200s // Recharge à t=150s avec niveau 50000 // À t=200s, la jauge a été rechargée et n'est plus à 0 const enc = buildEnclos(dd, { startGl: 100, elapsedSec: 200, recharges: [{ atSec: 150, level: 50000 }], currentGl: 50000, }); const result = computeGaugeLive(enc, dd, 'baffeur', 200, true); // La jauge rechargée à 50000 a eu 50s pour se vider (200-150) // Elle doit être > 0 (50000 pts se vide en bien plus de 50s) expect(result.curGl).toBeGreaterThan(0); // Le countdown doit être fini (pas Infinity) et positif expect(isFinite(result.cntDown)).toBe(true); expect(result.cntDown).toBeGreaterThan(0); }); it('enclosGlobalState retourne un globalMax fini après recharge', () => { const dd = createDragodinde(1); const enc = buildEnclos(dd, { startGl: 100, elapsedSec: 200, recharges: [{ atSec: 150, level: 50000 }], currentGl: 50000, }); const state = enclosGlobalState(enc); expect(state.started).toBe(true); expect(isFinite(state.globalMax)).toBe(true); expect(state.globalMax).toBeGreaterThan(0); }); });