§
    Ç½j.  ã                   ó‚  — d Z ddlZddlZddlZddlmZ  ee¦  «                             ¦   «         j        j        j        Z	de
defd„Z G d„ dej        ¦  «        Z G d	„ d
ej        ¦  «        Z G d„ dej        ¦  «        Z G d„ dej        ¦  «        Z G d„ dej        ¦  «        Zedk    r ej        ¦   «          dS dS )z—
Empirical Challenger Gen 3 Deep Stress & Verification Harness for Milestone 1.
Tests every fix independently with hostile, boundary, and fuzz inputs.
é    N)ÚPathÚjs_codeÚreturnc                 óð   — d| › d�}t          j        ddd|gddt          t          ¦  «        ¬¦  «        }|j        dk    rt          d	|j        › d
|j        › �¦  «        ‚t          j        |j	        ¦  «        S )zHExecutes ES module code in Node.js with mock DOM and canvas environment.a_  
const createMockElement = (id) => {
  const children = new Map();
  return {
    id, dataset: {},
    classList: {
      _c: new Set(),
      add(c) { this._c.add(c); }, remove(c) { this._c.delete(c); },
      toggle(c, f) { f = f === undefined ? !this._c.has(c) : f; f ? this._c.add(c) : this._c.delete(c); return f; },
      contains(c) { return this._c.has(c); }
    },
    style: { _p: {}, setProperty(k, v) { this._p[k] = v; }, getProperty(k) { return this._p[k]; } },
    innerText: '', textContent: '', offsetWidth: 44, offsetHeight: 44, _listeners: {},
    addEventListener(e, fn) { (this._listeners[e] = this._listeners[e] || []).push(fn); },
    dispatchEvent(e) { (this._listeners[e.type] || []).forEach(fn => fn(e)); },
    getContext: () => ({
      clearRect: () => {}, save: () => {}, restore: () => {}, beginPath: () => {},
      arc: () => {}, clip: () => {}, fillRect: () => {}, moveTo: () => {}, lineTo: () => {},
      closePath: () => {}, fill: () => {}, stroke: () => {}, ellipse: () => {},
      createRadialGradient: () => ({ addColorStop: () => {} }),
      createLinearGradient: () => ({ addColorStop: () => {} })
    }),
    querySelector(sel) {
      if (!children.has(sel)) children.set(sel, createMockElement('sub_' + sel));
      return children.get(sel);
    }
  };
};
const mockDoc = {
  'life-orb-canvas': createMockElement('life-orb-canvas'), 'mana-orb-canvas': createMockElement('mana-orb-canvas'),
  'txt-life-cur': createMockElement('txt-life-cur'), 'txt-life-max': createMockElement('txt-life-max'),
  'txt-mana-cur': createMockElement('txt-mana-cur'), 'txt-mana-max': createMockElement('txt-mana-max'),
  'hud-life-orb': createMockElement('hud-life-orb'), 'hud-mana-orb': createMockElement('hud-mana-orb'),
  'life-orb-warning': createMockElement('life-orb-warning'), 'hud-low-hp-vignette': createMockElement('hud-low-hp-vignette'),
  'hud-skill-bar': createMockElement('hud-skill-bar'), 'skill-potion': createMockElement('skill-potion'),
  'skill-fire': createMockElement('skill-fire'), 'skill-slot-w': createMockElement('skill-slot-w'),
  'skill-thunder': createMockElement('skill-thunder'), 'skill-frost': createMockElement('skill-frost'),
  'skill-primary': createMockElement('skill-primary'), 'skill-dodge': createMockElement('skill-dodge')
};
global.windowListeners = {};
global.document = {
  getElementById: (id) => mockDoc[id] || createMockElement(id),
  querySelector: (s) => createMockElement(s), readyState: 'complete',
  addEventListener: () => {}, activeElement: null
};
global.window = {
  addEventListener: (e, fn) => { (global.windowListeners[e] = global.windowListeners[e] || []).push(fn); },
  removeEventListener: (e, fn) => {
    if (global.windowListeners[e]) global.windowListeners[e] = global.windowListeners[e].filter(f => f !== fn);
  },
  performance: { now: () => Date.now() }, triggerHaptic: () => {},
  drinkHealthPotion: () => {}, doFire: () => {}, doThunder: () => {},
  doFrost: () => {}, doPrimaryAttack: () => {}, doDodge: () => {}, dodgeCharges: 3
};
global.performance = global.window.performance;
global.requestAnimationFrame = (fn) => 1;
global.cancelAnimationFrame = () => {};

try {
  z:
} catch (err) {
  console.error(err); process.exit(1);
}
Únodez--input-type=modulez-eT)Úcapture_outputÚtextÚcwdr   zNode execution failed (code z):
)
Ú
subprocessÚrunÚstrÚPROJECT_ROOTÚ
returncodeÚRuntimeErrorÚstderrÚjsonÚloadsÚstdout)r   Ú	bootstrapÚress      úBC:\Projects\FreeExile\tests\unit\test_challenger_gen3_empirical.pyÚrun_node_evalr      s˜   € ð?ðv ðw?ð ?ð ?€Iõ@ Œ.Ø	Ð&¨¨iÐ8Ø $­CµÑ,=Ô,=ðñ ô €Cð „~˜ÒÐÝÐZ¸#¼.ÐZÐZÈcÌjÐZÐZÑ[Ô[Ð[ÝŒ:�c”jÑ!Ô!Ð!ó    c                   ó   — e Zd ZdZd„ ZdS )ÚTestHudOrbsHostileInputszPHostile fuzzing of HudOrbs.update with non-finite, negative, and extreme values.c                 ó  — d}t          |¦  «        }|                      |d         ¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d         d¦  «         dS )zCTests permutations of NaN, Infinity, -Infinity in all 5 parameters.aU  
        const { HudOrbs } = await import('./client/webapp/js/ui/hud_orbs.js');
        HudOrbs.init();
        const testCases = [
          [NaN, 100, 50, 50, 0.016], [100, NaN, 50, 50, 0.016],
          [100, 100, NaN, 50, 0.016], [100, 100, 50, NaN, 0.016],
          [100, 100, 50, 50, NaN], [Infinity, 100, 50, 50, 0.016],
          [-Infinity, 100, 50, 50, 0.016], [100, Infinity, 50, 50, 0.016],
          [100, 100, Infinity, 50, 0.016], [100, 100, 50, Infinity, 0.016],
          [undefined, null, "string", Object.create(null), []]
        ];
        let poisonedAny = false;
        for (const tc of testCases) {
          HudOrbs.update(...tc);
          if (!Number.isFinite(HudOrbs.displayedHp) || !Number.isFinite(HudOrbs.displayedMana)) {
            poisonedAny = true; break;
          }
        }
        HudOrbs.update(75, 100, 40, 50, 0.016);
        console.log(JSON.stringify({
          poisonedAny, isHpFinite: Number.isFinite(HudOrbs.displayedHp),
          isManaFinite: Number.isFinite(HudOrbs.displayedMana), hp: HudOrbs.displayedHp
        }));
        process.exit(0);
        ÚpoisonedAnyÚ
isHpFiniteÚisManaFiniteÚhpr   N)r   ÚassertFalseÚ
assertTrueÚassertGreater©ÚselfÚjsÚdatas      r   Útest_nan_and_infinity_matrixz5TestHudOrbsHostileInputs.test_nan_and_infinity_matrix\   s   € ðˆõ2 ˜RÑ Ô ˆØ×Ò˜˜mÔ,Ñ-Ô-Ð-Ø�Š˜˜\Ô*Ñ+Ô+Ð+Ø�Š˜˜^Ô,Ñ-Ô-Ð-Ø×Ò˜4 œ: qÑ)Ô)Ð)Ð)Ð)r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r(   © r   r   r   r   Y   s)   € € € € € ØZÐZð*ð *ð *ð *ð *r   r   c                   ó   — e Zd ZdZd„ ZdS )Ú+TestSkillBarCooldownDurationZeroAndNegativezMEmpirical verification that duration <= 0 clears cooldown and resets charges.c                 óp  — d}t          |¦  «        }|                      |d         ¦  «         |                      |d         d¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d         d¦  «         |                      |d	         ¦  «         d S )
Na‚  
        const { SkillBarController } = await import('./client/webapp/js/ui/skill_bar_controller.js');
        const ctrl = new SkillBarController();
        ctrl.init();
        ctrl.registerSlot('test_normal', { cooldownTotal: 4.0 });
        ctrl.registerSlot('test_charge', { cooldownTotal: 3.0, charges: 3, rechargeDuration: 3.0 });
        ctrl.triggerCooldown('test_normal', 4.0);
        ctrl.triggerCooldown('test_charge', 3.0);
        const resZero = ctrl.triggerCooldown('test_normal', 0);
        const normalAfterZero = ctrl.getRemainingCooldown('test_normal');
        const normalIsOnCd = ctrl.isSlotOnCooldown('test_normal');
        const resNeg = ctrl.triggerCooldown('test_charge', -5.0);
        const chargeAfterNeg = ctrl.slots.get('test_charge').charges;
        const chargeIsOnCd = ctrl.isSlotOnCooldown('test_charge');
        ctrl.registerSlot('test_inf', { cooldownTotal: 2.0 });
        const resInf = ctrl.triggerCooldown('test_inf', Infinity);
        console.log(JSON.stringify({
          resZero, normalAfterZero, normalIsOnCd, resNeg, chargeAfterNeg, chargeIsOnCd, resInf
        }));
        process.exit(0);
        ÚresZeroÚnormalAfterZeror   ÚnormalIsOnCdÚresNegÚchargeAfterNegé   ÚchargeIsOnCd)r   r"   ÚassertEqualr!   r$   s      r   Ú/test_duration_zero_and_negative_clears_cooldownz[TestSkillBarCooldownDurationZeroAndNegative.test_duration_zero_and_negative_clears_cooldown�   s´   € ðˆõ* ˜RÑ Ô ˆØ�Š˜˜YœÑ(Ô(Ð(Ø×Ò˜Ð/Ô0°!Ñ4Ô4Ð4Ø×Ò˜˜nÔ-Ñ.Ô.Ð.Ø�Š˜˜XœÑ'Ô'Ð'Ø×Ò˜Ð.Ô/°Ñ3Ô3Ð3Ø×Ò˜˜nÔ-Ñ.Ô.Ð.Ð.Ð.r   N)r)   r*   r+   r,   r9   r-   r   r   r/   r/   ~   s)   € € € € € ØWÐWð/ð /ð /ð /ð /r   r/   c                   ó   — e Zd ZdZd„ ZdS )Ú&TestDodgeChargesVisualAndStateRecoveryzZEmpirical verification that Dodge recovers from 0 to 1 with visual reset and badge update.c                 óà  — d}t          |¦  «        }|                      |d         d¦  «         |                      |d         ¦  «         |                      |d         d¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d	         d¦  «         |                      |d
         d¦  «         |                      |d         ¦  «         d S )Na.  
        const { SkillBarController } = await import('./client/webapp/js/ui/skill_bar_controller.js');
        const ctrl = new SkillBarController();
        ctrl.init();
        const slot = ctrl.slots.get('dodge');
        let readyCallbackFired = false;
        ctrl.onReady('dodge', () => { readyCallbackFired = true; });
        ctrl.activateSlot('dodge'); ctrl.activateSlot('dodge'); ctrl.activateSlot('dodge');
        const chargesDepleted = slot.charges;
        const hasClassOnCd = slot.element.classList.contains('is-on-cooldown');
        ctrl._updateAllCooldowns(3.1);
        console.log(JSON.stringify({
          chargesDepleted, hasClassOnCd,
          chargesRecovered: slot.charges,
          isOnCdRecovered: ctrl.isSlotOnCooldown('dodge'),
          hasClassOnCdAfter: slot.element.classList.contains('is-on-cooldown'),
          windowChargesSynced: global.window.dodgeCharges,
          badgeTextRecovered: slot.element.querySelector('.skill-charges-badge').textContent,
          readyCallbackFired
        }));
        process.exit(0);
        ÚchargesDepletedr   ÚhasClassOnCdÚchargesRecoveredé   ÚisOnCdRecoveredÚhasClassOnCdAfterÚwindowChargesSyncedÚbadgeTextRecoveredÚ1ÚreadyCallbackFired)r   r8   r"   r!   r$   s      r   Ú&test_dodge_charge_zero_to_one_recoveryzMTestDodgeChargesVisualAndStateRecovery.test_dodge_charge_zero_to_one_recovery£   sñ   € ðˆõ, ˜RÑ Ô ˆØ×Ò˜Ð/Ô0°!Ñ4Ô4Ð4Ø�Š˜˜^Ô,Ñ-Ô-Ð-Ø×Ò˜Ð0Ô1°1Ñ5Ô5Ð5Ø×Ò˜Ð/Ô0Ñ1Ô1Ð1Ø×Ò˜Ð1Ô2Ñ3Ô3Ð3Ø×Ò˜Ð3Ô4°aÑ8Ô8Ð8Ø×Ò˜Ð2Ô3°SÑ9Ô9Ð9Ø�Š˜Ð1Ô2Ñ3Ô3Ð3Ð3Ð3r   N)r)   r*   r+   r,   rG   r-   r   r   r;   r;       s)   € € € € € ØdÐdð4ð 4ð 4ð 4ð 4r   r;   c                   ó   — e Zd ZdZd„ ZdS )ÚTestKeybindingWDisambiguationzCEmpirical verification that Key 'W' does NOT activate skill slot 2.c                 ón  — d}t          |¦  «        }|                      |d         ¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d         ¦  «         |                      |d         d¦  «         d S )	Na*  
        const { SkillBarController } = await import('./client/webapp/js/ui/skill_bar_controller.js');
        const ctrl = new SkillBarController();
        ctrl.init();
        let slot2Activated = false;
        const slot2 = ctrl.slots.get('2');
        slot2.onActivate = () => { slot2Activated = true; };
        const resLowerW = ctrl.handleKeyPress('w');
        const resUpperW = ctrl.handleKeyPress('W');
        const keydownHandlers = global.windowListeners['keydown'] || [];
        for (const handler of keydownHandlers) {
          handler({ key: 'w', preventDefault: () => {} });
          handler({ key: 'W', preventDefault: () => {} });
        }
        const wasActivatedByW = slot2Activated;
        const resKey2 = ctrl.handleKeyPress('2');
        for (const handler of keydownHandlers) handler({ key: '2', preventDefault: () => {} });
        console.log(JSON.stringify({
          resLowerW, resUpperW, wasActivatedByW, resKey2,
          wasActivatedByKey2: slot2Activated, slot2Key: slot2.key
        }));
        process.exit(0);
        Ú	resLowerWÚ	resUpperWÚwasActivatedByWÚresKey2ÚwasActivatedByKey2Úslot2KeyÚ2)r   r!   r"   r8   r$   s      r   Ú$test_w_key_does_not_activate_skill_2zBTestKeybindingWDisambiguation.test_w_key_does_not_activate_skill_2È   s³   € ðˆõ. ˜RÑ Ô ˆØ×Ò˜˜kÔ*Ñ+Ô+Ð+Ø×Ò˜˜kÔ*Ñ+Ô+Ð+Ø×Ò˜Ð/Ô0Ñ1Ô1Ð1Ø�Š˜˜YœÑ(Ô(Ð(Ø�Š˜Ð1Ô2Ñ3Ô3Ð3Ø×Ò˜˜jÔ)¨3Ñ/Ô/Ð/Ð/Ð/r   N)r)   r*   r+   r,   rR   r-   r   r   rI   rI   Å   s)   € € € € € ØMÐMð0ð 0ð 0ð 0ð 0r   rI   c                   ó   — e Zd ZdZd„ ZdS )Ú!TestRapidSpamAndConcurrencyStresszN1000 spam calls and concurrency simulation without desync or memory explosion.c                 óÐ   — d}t          |¦  «        }|                      |d         d¦  «         |                      |d         d¦  «         |                      |d         d¦  «         d S )Na3  
        const { SkillBarController } = await import('./client/webapp/js/ui/skill_bar_controller.js');
        const ctrl = new SkillBarController();
        ctrl.init();
        const t0 = Date.now();
        for (let i = 0; i < 1000; i++) {
          ctrl.activateSlot('1'); ctrl.triggerCooldown('1', 1.5);
        }
        const elapsedMs = Date.now() - t0;
        console.log(JSON.stringify({
          elapsedMs, finalRemaining: ctrl.getRemainingCooldown('1'),
          uniqueSlotsSize: ctrl.uniqueSlots.size
        }));
        process.exit(0);
        Ú	elapsedMsiè  ÚfinalRemainingg      ø?ÚuniqueSlotsSizeé   )r   Ú
assertLessr8   r$   s      r   Ú'test_1000_spam_activations_and_triggerszITestRapidSpamAndConcurrencyStress.test_1000_spam_activations_and_triggersì   so   € ðˆõ ˜RÑ Ô ˆØ�Š˜˜[Ô)¨4Ñ0Ô0Ð0Ø×Ò˜Ð.Ô/°Ñ5Ô5Ð5Ø×Ò˜Ð/Ô0°!Ñ4Ô4Ð4Ð4Ð4r   N)r)   r*   r+   r,   r[   r-   r   r   rT   rT   é   s)   € € € € € ØXÐXð5ð 5ð 5ð 5ð 5r   rT   Ú__main__)r,   r   r   ÚunittestÚpathlibr   Ú__file__ÚresolveÚparentr   r   Údictr   ÚTestCaser   r/   r;   rI   rT   r)   Úmainr-   r   r   ú<module>re      s—  ððð ð
 €€€Ø Ð Ð Ð Ø €€€Ø Ð Ð Ð Ð Ð àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€ðH"˜3ð H" 4ð H"ð H"ð H"ð H"ðV"*ð "*ð "*ð "*ð "*˜xÔ0ñ "*ô "*ð "*ðJ/ð /ð /ð /ð /°(Ô2Cñ /ô /ð /ðD"4ð "4ð "4ð "4ð "4¨XÔ->ñ "4ô "4ð "4ðJ!0ð !0ð !0ð !0ð !0 HÔ$5ñ !0ô !0ð !0ðH5ð 5ð 5ð 5ð 5¨Ô(9ñ 5ô 5ð 5ð2 ˆzÒÐØ€H„M�O„O€O€O€Oð Ðr   