42 lines
2.6 KiB
TypeScript
42 lines
2.6 KiB
TypeScript
import assert from 'node:assert/strict';
|
||
import test from 'node:test';
|
||
import { createElement, type ReactElement } from 'react';
|
||
import { renderToStaticMarkup } from 'react-dom/server';
|
||
import { Truthtrance } from '../components/truthtrance';
|
||
import { TraitorDecisionAnswers, TraitorDecisionPromises } from '../components/traitor-decision-promises';
|
||
import { viewGame, type Action } from '../game/engine';
|
||
import { createTruthTraitorDecisionFixture as fixture, actTruthTraitorDecision as act,
|
||
askTruthTraitorDecision as ask } from './fixture-truth-traitor-decision';
|
||
|
||
function callbacks(node: unknown): (() => void)[] {
|
||
if (Array.isArray(node)) return node.flatMap(callbacks);
|
||
if (!node || typeof node !== 'object' || !('props' in node)) return [];
|
||
const props = (node as ReactElement<{ children?: unknown; onClick?: () => void }>).props;
|
||
return [...(props.onClick ? [props.onClick] : []), ...callbacks(props.children)];
|
||
}
|
||
|
||
void test('actual current-decision answer controls and persistent declaration notice explain later prevention', () => {
|
||
const f = fixture(); let g = ask(f.game, f.asker, f.truth, f.target);
|
||
const html = renderToStaticMarkup(createElement(Truthtrance,
|
||
{ game: viewGame(g, f.target), busy: false, act() {} }));
|
||
assert.match(html, /Answer Yes/); assert.match(html, /Answer No/);
|
||
assert.match(html, /later Karama or betrayal response/);
|
||
const actions: Action[] = [], props = { game: viewGame(g, f.target), busy: false, act: (action: Action) => { actions.push(action); } };
|
||
callbacks(TraitorDecisionAnswers(props))[1]();
|
||
assert.deepEqual(actions, [{ type: 'truthAnswer', answer: 'yes' }]);
|
||
callbacks(TraitorDecisionAnswers({ ...props, busy: true }))[1](); assert.equal(actions.length, 1);
|
||
g = act(g, f.target, actions[0]);
|
||
const notice = renderToStaticMarkup(createElement(TraitorDecisionPromises, { game: viewGame(g, f.target) }));
|
||
assert.match(notice, /requires Reveal traitor/);
|
||
assert.match(notice, /original declaration fulfills your answer/);
|
||
assert.equal(TraitorDecisionPromises({ game: viewGame(g, f.asker) }), null);
|
||
});
|
||
|
||
void test('only the current declared battle has the new question authoring choice', () => {
|
||
const f = fixture(); let g = act(f.game, f.asker, { type: 'card', card: f.truth });
|
||
for (const p of g.players) if (!g.truthtrance!.passed.includes(p.id)) g = act(g, p.id, { type: 'truthPass' });
|
||
const html = renderToStaticMarkup(createElement(Truthtrance, { game: viewGame(g, f.asker), busy: false, act() {} }));
|
||
assert.match(html, /Bind this battle’s Traitor declaration/);
|
||
assert.ok(viewGame(g, f.asker).truthTraitorTargets.includes(f.target));
|
||
});
|