Files
Dune/tests/truth-future-battle-leader-controls.test.tsx
Quintine 02695aea7c
Verify and publish checkpoint container / container (push) Failing after 11m11s
Prototype conditional future battle Truthtrance
2026-10-28 21:17:44 +11:00

70 lines
3.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict';
import test from 'node:test';
import { createElement, isValidElement, type ReactElement, type ReactNode } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { TruthFutureBattleLeader } from '../components/truth-future-battle-leader';
import { createGame, joinGame, newPlayer, viewGame, type GameView } from '../game/engine';
type ElementProps = { children?: ReactNode; [key: string]: unknown };
type Element = ReactElement<ElementProps>;
function elements(node: ReactNode): Element[] {
if (Array.isArray(node)) return node.flatMap(elements);
if (!isValidElement<ElementProps>(node)) return [];
return [node, ...elements(node.props.children)];
}
function control(node: ReactNode, id: string): Element {
const result = elements(node).find(element => element.props['data-testid'] === id);
assert.ok(result, `Expected ${id}`);
return result;
}
function projection(): GameView {
const game = createGame('TRUTHFUTURE', newPlayer('asker', 'Asker', 'atreides'), false);
joinGame(game, newPlayer('target', 'Target', 'emperor'));
joinGame(game, newPlayer('other', 'Other', 'harkonnen'));
return viewGame(game, 'asker');
}
void test('future battle question lists only the target faction’s public native leaders', () => {
const game = projection();
const native = game.allLeaders.find(item => item.faction === 'emperor');
const other = game.allLeaders.find(item => item.faction === 'harkonnen');
assert.ok(native && other);
const props = { game, target: 'target', leader: native.id, available: true, busy: false,
onLeaderChange: (_leader: string) => {}, onAsk: (_target: string, _leader: string) => {} };
const html = renderToStaticMarkup(createElement(TruthFutureBattleLeader, props));
assert.match(html, /If you fight a battle later this turn/);
assert.match(html, /first such battle/);
assert.match(html, /there is no opportunity/);
assert.ok(html.includes(native.name));
assert.ok(!html.includes(other.name));
assert.equal(control(TruthFutureBattleLeader(props), 'truth-future-battle-leader-ask').props.disabled, false);
});
void test('authoring callbacks reject unavailable, missing and foreign leaders', () => {
const game = projection();
const native = game.allLeaders.filter(item => item.faction === 'emperor');
const foreign = game.allLeaders.find(item => item.faction === 'harkonnen');
assert.ok(native.length >= 2 && foreign);
const changes: string[] = [], asks: string[][] = [];
const props = { game, target: 'target', leader: '', available: true, busy: false,
onLeaderChange: (id: string) => changes.push(id),
onAsk: (target: string, id: string) => asks.push([target, id]) };
const change = (tree: ReactNode, value: string) =>
(control(tree, 'truth-future-battle-leader-select').props.onChange as (event: { target: { value: string } }) => void)({ target: { value } });
const ask = (tree: ReactNode) => (control(tree, 'truth-future-battle-leader-ask').props.onClick as () => void)();
const empty = TruthFutureBattleLeader(props);
assert.equal(control(empty, 'truth-future-battle-leader-ask').props.disabled, true);
change(empty, foreign.id); ask(empty); assert.deepEqual(changes, []); assert.deepEqual(asks, []);
change(empty, native[1].id); assert.deepEqual(changes, [native[1].id]);
const selected = TruthFutureBattleLeader({ ...props, leader: native[1].id });
ask(selected); assert.deepEqual(asks, [['target', native[1].id]]);
for (const override of [{ busy: true }, { available: false }, { leader: foreign.id }, { target: 'asker' }]) {
const tree = TruthFutureBattleLeader({ ...props, leader: native[1].id, ...override });
assert.equal(control(tree, 'truth-future-battle-leader-ask').props.disabled, true);
ask(tree);
}
assert.equal(asks.length, 1);
});