Files
Dune/tests/emperor-extortion-priority-controls.test.tsx
T
Quintine 7c1f4b4e09
Verify and publish checkpoint container / container (push) Successful in 10m54s
Preserve Emperor gift opportunity before bot Extortion
2026-10-30 17:44:00 +11:00

58 lines
3.0 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { Children, createElement, isValidElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import type { Action } from '../game/engine';
import { EmperorExtortionPriority, type EmperorExtortionPriorityProps } from '../components/emperor-extortion-priority';
function props(): EmperorExtortionPriorityProps & { sent: Action[] } {
const sent: Action[] = [];
return {game:{emperorExtortionPriority:{event:'extortion-event',recipient:'ally',canContinue:true},
players:[{id:'ally',name:'Ally'}]}, busy:false, sent, act(action) {sent.push(action);}};
}
const render = (input: EmperorExtortionPriorityProps) => renderToStaticMarkup(createElement(EmperorExtortionPriority, input));
function button(input: EmperorExtortionPriorityProps) {
const section = EmperorExtortionPriority(input); assert.ok(section);
const match = Children.toArray(section.props.children).find(child => isValidElement(child) &&
(child.props as {'data-testid'?: string})['data-testid'] === 'emperor-extortion-continue');
assert.ok(isValidElement<{onClick:() => void; disabled:boolean}>(match));
return match;
}
void test('the Emperor sees a persistent, event-bound Extortion opportunity', () => {
const input = props(), html = render(input);
assert.match(html, /Before Ally makes the Extortion choice/);
assert.match(html, /Continue to Extortion/);
assert.equal(button(input).props.disabled, false);
button(input).props.onClick();
assert.deepEqual(input.sent, [{type:'emperorExtortionContinue',event:'extortion-event'}]);
});
void test('other viewers see the same neutral opportunity without a Continue control or private data', () => {
const input = props();
input.game.emperorExtortionPriority!.canContinue = false;
Object.assign(input.game, {privateSpice:19, privateCard:'secret-card'});
const html = render(input);
assert.match(html, /Waiting for the Emperor/);
assert.doesNotMatch(html, /emperor-extortion-continue|secret-card|19/);
assert.deepEqual(input.sent, []);
input.game.emperorExtortionPriority = null;
assert.equal(render(input), '');
});
void test('busy, invalid, stale or consumed opportunities cannot submit', () => {
for (const change of ['busy','empty','event','permission','replace','close'] as const) {
const input = props();
if (change === 'busy') input.busy = true;
if (change === 'empty') input.game.emperorExtortionPriority!.event = '';
const control = button(input);
if (change === 'busy' || change === 'empty') assert.equal(control.props.disabled, true);
if (change === 'event') input.game.emperorExtortionPriority!.event = 'other';
if (change === 'permission') input.game.emperorExtortionPriority!.canContinue = false;
if (change === 'replace') input.game.emperorExtortionPriority = {...input.game.emperorExtortionPriority!};
if (change === 'close') input.game.emperorExtortionPriority = null;
control.props.onClick();
assert.deepEqual(input.sent, [], change);
}
});