53 lines
2.3 KiB
JavaScript
53 lines
2.3 KiB
JavaScript
|
|
// DRY guard (BUG-5 fix): nextTurn and computeTurnOrderAfterRemoval share one
|
||
|
|
// advance core (nextActiveAfter). Both must pick the SAME next-active target
|
||
|
|
// for identical state. If this goes RED, the two paths drifted.
|
||
|
|
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
const shared = require('@ttrpg/shared');
|
||
|
|
const { makeParticipant, startEncounter, nextTurn, toggleParticipantActive } = shared;
|
||
|
|
|
||
|
|
function p(id, init, extra = {}) {
|
||
|
|
return makeParticipant({ id, name: id, type: 'monster',
|
||
|
|
initiative: init, maxHp: 100, currentHp: 100, ...extra });
|
||
|
|
}
|
||
|
|
function enc(ps, extra = {}) {
|
||
|
|
return { name:'t', participants:ps, isStarted:false, isPaused:false,
|
||
|
|
round:0, currentTurnParticipantId:null, turnOrderIds:[], ...extra };
|
||
|
|
}
|
||
|
|
|
||
|
|
describe('DRY: deact-current advance == nextTurn advance', () => {
|
||
|
|
test('mid-round: same target (not current)', () => {
|
||
|
|
// order a,b,c. a current. nextTurn → b. deact a → advance → b.
|
||
|
|
const e = enc([p('a',10),p('b',5),p('c',3)], { isStarted:true,
|
||
|
|
turnOrderIds:['a','b','c'], currentTurnParticipantId:'a' });
|
||
|
|
const nt = nextTurn(e).patch.currentTurnParticipantId;
|
||
|
|
const deact = toggleParticipantActive(e, 'a').patch.currentTurnParticipantId;
|
||
|
|
expect(deact).toBe(nt);
|
||
|
|
expect(deact).toBe('b');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('mid-round with inactive skipper: same target', () => {
|
||
|
|
// order a,x,b,c; x inactive. a current. nextTurn → b. deact a → b.
|
||
|
|
const x = p('x',7,{ isActive:false });
|
||
|
|
const e = enc([p('a',10),x,p('b',5),p('c',3)], { isStarted:true,
|
||
|
|
turnOrderIds:['a','x','b','c'], currentTurnParticipantId:'a' });
|
||
|
|
const nt = nextTurn(e).patch.currentTurnParticipantId;
|
||
|
|
const deact = toggleParticipantActive(e, 'a').patch.currentTurnParticipantId;
|
||
|
|
expect(deact).toBe(nt);
|
||
|
|
expect(deact).toBe('b');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('wrap: same target + round bump', () => {
|
||
|
|
// order a,b,c. c current. nextTurn → wrap → a (r+1). deact c → wrap → a (r+1).
|
||
|
|
const e = enc([p('a',10),p('b',5),p('c',3)], { isStarted:true,
|
||
|
|
turnOrderIds:['a','b','c'], currentTurnParticipantId:'c', round:2 });
|
||
|
|
const nt = nextTurn(e).patch;
|
||
|
|
const deact = toggleParticipantActive(e, 'c').patch;
|
||
|
|
expect(deact.currentTurnParticipantId).toBe(nt.currentTurnParticipantId);
|
||
|
|
expect(deact.currentTurnParticipantId).toBe('a');
|
||
|
|
expect(deact.round).toBe(nt.round);
|
||
|
|
expect(deact.round).toBe(3);
|
||
|
|
});
|
||
|
|
});
|