Files
Dune/tests/sapho-suspended-replay-helper.test.ts
T

73 lines
3.5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
reorderSaphoMovementOrder, saphoMovementOrderEvent, SaphoMovementOrderError,
type SaphoMovementOrderContext,
} from '../game/sapho-movement-order';
function context(currentStarted = false): SaphoMovementOrderContext {
return {
queue: {
event: 'movement:3', eligible: ['done', 'current', 'later', 'holder'],
remaining: ['current', 'later', 'holder'], completed: ['done'],
current: 'current', currentStarted, protectedLast: 'holder',
},
started: currentStarted ? ['done', 'current', 'holder'] : ['done', 'holder'],
guild: null,
};
}
function change(input: SaphoMovementOrderContext, player = 'holder', mode: 'first' | 'last' = 'first') {
return reorderSaphoMovementOrder(input, { event: saphoMovementOrderEvent(input), player, mode });
}
void test('suspended holder resumes its existing started turn when First becomes current', () => {
const input = context(), before = structuredClone(input), result = change(input);
assert.deepEqual(result.next.remaining, ['holder', 'current', 'later']);
assert.deepEqual(result.next.completed, ['done']);
assert.equal(result.next.current, 'holder');
assert.equal(result.next.currentStarted, true);
assert.equal(result.next.protectedLast, null);
assert.equal(result.afterCurrent, null);
assert.equal(result.suspended, undefined);
assert.deepEqual(input, before);
});
void test('another started actor finishes before the suspended holder resumes', () => {
const input = context(true), before = structuredClone(input), result = change(input);
assert.deepEqual(result.next.remaining, ['current', 'holder', 'later']);
assert.deepEqual(result.next.completed, ['done']);
assert.equal(result.next.current, 'current');
assert.equal(result.next.currentStarted, true);
assert.equal(result.next.protectedLast, null);
assert.equal(result.afterCurrent, 'current');
assert.deepEqual(input, before);
});
void test('only the same holder can replace its protected suspended Last', () => {
const input = context(), before = structuredClone(input);
assert.throws(() => change(input, 'later', 'first'), SaphoMovementOrderError);
assert.throws(() => change(input, 'later', 'last'), SaphoMovementOrderError);
assert.throws(() => change(input, 'holder', 'last'), SaphoMovementOrderError);
assert.throws(() => reorderSaphoMovementOrder(input,
{ event: 'movement:4', player: 'holder', mode: 'first' }), SaphoMovementOrderError);
assert.deepEqual(input, before);
});
void test('unrelated started tails and inconsistent current start are rejected', () => {
const unrelated = context(); unrelated.started = ['done', 'later', 'holder'];
assert.throws(() => saphoMovementOrderEvent(unrelated), SaphoMovementOrderError);
const noProtection = context(); noProtection.queue = { ...noProtection.queue, protectedLast: null };
assert.throws(() => saphoMovementOrderEvent(noProtection), SaphoMovementOrderError);
const badCurrent = context(); badCurrent.started = ['current', 'holder'];
assert.throws(() => saphoMovementOrderEvent(badCurrent), SaphoMovementOrderError);
});
void test('a granted current Guild turn cannot be displaced by suspended First', () => {
const granted = context();
granted.guild = { player: 'current', granted: true, locked: false };
assert.throws(() => change(granted), SaphoMovementOrderError);
const currentStarted = context(true);
currentStarted.guild = { player: 'current', granted: true, locked: false };
assert.equal(change(currentStarted).afterCurrent, 'current');
});