Files
healer-man/scripts/weapon-evidence-recorder.test.cjs
2026-10-06 22:25:34 -04:00

69 lines
3.5 KiB
JavaScript

const { test } = require('node:test');
const assert = require('node:assert/strict');
const { createWeaponEvidenceRecorder } = require('./weapon-evidence-recorder.cjs');
function fixture() {
let state = { combatEvents: [], mobs: {}, auras: [] };
const listeners = new Set();
return { getState: () => state, subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
commit(next) { state = next; for (const fn of listeners) fn(state); },
listenerCount: () => listeners.size };
}
test('retains source shout parent and child timers without recording unrelated auras', () => {
const store = fixture(), recorder = createWeaponEvidenceRecorder(store, { clock: () => 123 });
const aura = (id) => ({ instanceId: id, definition: { id }, sourceId: 'boss', targetId: 'player',
appliedAt: 100, expiresAt: 5_100, stacks: 1 });
store.commit({ combatEvents: [], mobs: {}, auras: [
aura('enemy-control:source-spell-5246'), aura('enemy-control:source-spell-20511'), aura('unrelated'),
] });
assert.deepEqual(recorder.stop().auraSamples.at(-1).auras.map((entry) => entry.definitionId), [
'enemy-control:source-spell-5246', 'enemy-control:source-spell-20511',
]);
});
test('retains consecutive results beyond the HUD ring and unsubscribes without changing state', () => {
const store = fixture(), recorder = createWeaponEvidenceRecorder(store);
let history = [];
for (let id = 1; id <= 350; id++) {
history = [...history, { id, attackHand: 'offhand', rawAmount: 30 }].slice(-200);
store.commit({ combatEvents: history, mobs: {}, auras: [] });
}
const before = store.getState(), result = recorder.stop();
assert.equal(store.getState(), before);
assert.equal(result.events.length, 350);
assert.deepEqual(result.gaps, []);
assert.equal(result.events[349].attackHand, 'offhand');
assert.equal(store.listenerCount(), 0);
store.commit({ ...before, combatEvents: [...history, { id: 351 }] });
assert.equal(recorder.stop().events.length, 350);
});
test('reports dropped IDs and capacity overflow rather than claiming complete evidence', () => {
const store = fixture(), recorder = createWeaponEvidenceRecorder(store, { capacity: 2 });
store.commit({ combatEvents: [{ id: 3 }, { id: 4 }, { id: 5 }], mobs: {}, auras: [] });
const result = recorder.stop();
assert.deepEqual(result.gaps, [{ afterId: 0, beforeId: 3 }]);
assert.equal(result.discardedEvents, 1);
assert.equal(result.events.length, 2);
});
test('copies transient weapon queues and party debuffs between checkpoints', () => {
const store = fixture(), recorder = createWeaponEvidenceRecorder(store, { clock: () => 123 });
const pending = [{ id: 'thrash', remaining: 2, sourceSpellId: 3391 }];
const state = { combatEvents: [], mobs: { boss: { id: 'boss', name: 'Boss',
engaged: true, dualWieldEnabled: true, nextEnemyOffhandAttackAt: 200,
pendingExtraAttacks: pending } }, auras: [{ instanceId: 'tank-wound',
definition: { id: 'enemy-source-spell-17230', dispelCategory: 'disease' },
targetId: 'tank', sourceId: 'boss', appliedAt: 123, expiresAt: 300123, stacks: 1 }] };
store.commit(state);
pending[0].remaining = 0;
store.commit({ ...state, mobs: { boss: { ...state.mobs.boss,
pendingExtraAttacks: [], nextEnemyOffhandAttackAt: 400 } }, auras: [] });
const result = recorder.stop();
assert.equal(result.mobSamples[0].pendingExtraAttacks[0].remaining, 2);
assert.equal(result.mobSamples[1].nextEnemyOffhandAttackAt, 400);
assert.equal(result.auraSamples[1].auras[0].targetId, 'tank');
assert.deepEqual(result.auraSamples[2].auras, []);
});