import { describe, expect, it } from 'vitest';
import { PLAYER_COMBAT } from '../stats';
import { PlayerCombat } from '../PlayerCombat';
/** Тик на 1/60 с — как в игровом цикле. */
const step = (c: PlayerCombat, seconds: number): void => {
for (let i = 0; i < Math.round(seconds * 60); i++) c.update(1 / 60);
};
describe('PlayerCombat', () => {
it('стартует с полным здоровьем', () => {
const c = new PlayerCombat();
expect(c.hp).toBe(PLAYER_COMBAT.maxHp);
expect(c.dead).toBe(false);
expect(c.invuln).toBe(false);
});
it('урон не превышает остаток HP, после него неуязвимость', () => {
const c = new PlayerCombat();
expect(c.takeDamage(3)).toBe(3);
expect(c.hp).toBe(2);
expect(c.invuln).toBe(true);
// В окно неуязвимости урон не проходит
expect(c.takeDamage(1)).toBe(0);
expect(c.hp).toBe(2);
});
it('смерть при HP 0; revive возвращает полные сердечки', () => {
const c = new PlayerCombat();
c.takeDamage(PLAYER_COMBAT.maxHp);
expect(c.dead).toBe(true);
c.revive();
expect(c.hp).toBe(PLAYER_COMBAT.maxHp);
expect(c.dead).toBe(false);
expect(c.invuln).toBe(true);
});
it('короткий тап — удар по кулдауну', () => {
const c = new PlayerCombat();
c.startCharge();
step(c, 0.1);
expect(c.isCharging()).toBe(true);
expect(c.release()).toBe('attack');
// Кулдаун ещё не истёк — второй удар не проходит
c.startCharge();
step(c, 0.1);
expect(c.release()).toBeNull();
// После кулдауна снова готов
step(c, PLAYER_COMBAT.coneCooldown);
c.startCharge();
step(c, 0.1);
expect(c.release()).toBe('attack');
});
it('удержание дольше resonanceCharge — резонанс по своему кулдауну', () => {
const c = new PlayerCombat();
c.startCharge();
step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
expect(c.release()).toBe('resonance');
// Резонанс перезаряжается — повторный заряд молча отклоняется
c.startCharge();
step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
expect(c.release()).toBeNull();
step(c, PLAYER_COMBAT.resonanceCooldown);
c.startCharge();
step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
expect(c.release()).toBe('resonance');
});
it('неуязвимость спадает со временем', () => {
const c = new PlayerCombat();
c.takeDamage(1);
step(c, PLAYER_COMBAT.invulnTime + 0.05);
expect(c.invuln).toBe(false);
expect(c.takeDamage(1)).toBe(1);
});
});