// ─── Golem Combat Helpers Unit Tests (Issue #313) ────────────────────────────── // Unit tests for computeBasicAttackDamage and resolveEnchantmentEffects. import { describe, it, expect } from 'vitest'; import { computeBasicAttackDamage, resolveEnchantmentEffects } from './golem-combat-helpers'; // ─── computeBasicAttackDamage ──────────────────────────────────────────────── describe('computeBasicAttackDamage', () => { it('returns baseDamage with no armor and no elemental effect', () => { const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: undefined }, 0, 0, 'fire', ); expect(dmg).toBe(10); }); it('applies elemental bonus for super effective matchup', () => { // Water vs Fire = 1.5x (water is opposite of fire) const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: 'water' }, 0, 0, 'fire', ); expect(dmg).toBe(15); }); it('applies elemental penalty for weak matchup', () => { // Lightning vs Earth = 0.75x (lightning is weak to earth) const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: 'lightning' }, 0, 0, 'earth', ); expect(dmg).toBe(7.5); }); it('applies same-element bonus', () => { const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: 'fire' }, 0, 0, 'fire', ); expect(dmg).toBe(12.5); }); it('never returns negative damage', () => { const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: undefined }, 0, 0.99, 'fire', ); expect(dmg).toBeGreaterThanOrEqual(0); }); it('combines elemental bonus and armor pierce', () => { // Water vs Fire = 1.5x, then armor pierce adds to damage multiplier // dmg = 10 * 1.5 * (1 + 0.25) = 18.75 const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0.25, element: 'water' }, 0, 0.5, 'fire', ); expect(dmg).toBeCloseTo(18.75, 5); }); it('doubles damage when armorPierce is 1.0', () => { // dmg = 10 * (1 + 1.0) = 20 const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 1.0, element: undefined }, 0, 0.8, 'fire', ); expect(dmg).toBe(20); }); it('returns base damage when armorPierce is 0', () => { // dmg = 10 * (1 + 0) = 10 const dmg = computeBasicAttackDamage( { baseDamage: 10, armorPierce: 0, element: undefined }, 0, 0.5, 'fire', ); expect(dmg).toBe(10); }); it('stacks enchantment armorPierce with frame armorPierce', () => { // totalPierce = 0.5 + 0.15 = 0.65 // dmg = 20 * (1 + 0.65) = 33 const totalPierce = 0.5 + 0.15; const dmg = computeBasicAttackDamage( { baseDamage: 20, armorPierce: 0.5, element: undefined }, 0.15, 0.4, 'fire', ); expect(dmg).toBe(20 * (1 + totalPierce)); }); }); // ─── resolveEnchantmentEffects ──────────────────────────────────────────────── describe('resolveEnchantmentEffects', () => { it('resolves sword_fire to burn effect', () => { const effects = resolveEnchantmentEffects(['sword_fire']); expect(effects).toHaveLength(1); expect(effects[0].type).toBe('burn'); expect(effects[0].magnitude).toBe(3); }); it('resolves sword_frost to slow effect', () => { const effects = resolveEnchantmentEffects(['sword_frost']); expect(effects).toHaveLength(1); expect(effects[0].type).toBe('slow'); }); it('resolves sword_metal to armorPierce effect', () => { const effects = resolveEnchantmentEffects(['sword_metal']); expect(effects).toHaveLength(1); expect(effects[0].type).toBe('armorPierce'); expect(effects[0].magnitude).toBe(0.15); }); it('resolves sword_lightning to shock effect', () => { const effects = resolveEnchantmentEffects(['sword_lightning']); expect(effects).toHaveLength(1); expect(effects[0].type).toBe('shock'); }); it('resolves sword_shadow to weaken effect', () => { const effects = resolveEnchantmentEffects(['sword_shadow']); expect(effects).toHaveLength(1); expect(effects[0].type).toBe('weaken'); }); it('returns empty array for unknown enchantment IDs', () => { const effects = resolveEnchantmentEffects(['nonexistent_enchant']); expect(effects).toHaveLength(0); }); it('resolves multiple enchantments', () => { const effects = resolveEnchantmentEffects(['sword_fire', 'sword_lightning', 'sword_shadow']); expect(effects).toHaveLength(3); const types = effects.map(e => e.type); expect(types).toContain('burn'); expect(types).toContain('shock'); expect(types).toContain('weaken'); }); it('handles empty array', () => { const effects = resolveEnchantmentEffects([]); expect(effects).toHaveLength(0); }); });