77 lines
4.1 KiB
TypeScript
77 lines
4.1 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { registerHooks } from 'node:module';
|
|
import { readFileSync } from 'node:fs';
|
|
import { createElement } from 'react';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { viewGame, type Game } from '../game/engine';
|
|
import { createTruthTurnAmalFixture } from './fixture-truth-turn-amal';
|
|
import { actTruthCharityPayments as act, advanceTruthCharityPayments as advance,
|
|
createTruthCharityPaymentsFixture, truthCharityPaymentsClean as clean,
|
|
truthCharityPaymentsInventory as inventory } from './fixture-truth-charity-payments';
|
|
|
|
const aliases = registerHooks({
|
|
resolve(specifier,context,next) {
|
|
return next(specifier === 'next/image' ? 'vinext/shims/image' :
|
|
specifier === 'next/link' ? 'vinext/shims/link' : specifier,context);
|
|
},
|
|
load(url,context,next) {
|
|
if (!url.endsWith('.module.css')) return next(url,context);
|
|
const css = readFileSync(new URL(url),'utf8');
|
|
const classes = Object.fromEntries([...css.matchAll(/\.([a-zA-Z_][\w-]*)/g)].map(match => [match[1],match[1]]));
|
|
return {format:'module',source:`export default ${JSON.stringify(classes)}`,shortCircuit:true};
|
|
},
|
|
});
|
|
const {Truthtrance} = await import('../components/truthtrance');
|
|
const {TruthCharityPromise} = await import('../components/truth-charity-promise');
|
|
aliases.deregister();
|
|
|
|
/** Actual Advanced setup and original Truth cards; phase 1 also plays Amal.
|
|
* The native fixture selects only unopened starting cards and Spice order. */
|
|
function fixture(phase:0|1) {
|
|
const base = phase === 0 ? createTruthTurnAmalFixture({phase:0,advanced:true})
|
|
: createTruthCharityPaymentsFixture({source:'afterAmal',advanced:true});
|
|
const game = phase === 0
|
|
? advance(structuredClone(base.game), state => state.phase === 0 && clean(state), [], true)
|
|
: structuredClone(base.game);
|
|
assert.equal(game.phase,phase); assert.equal(game.advanced,true); assert.ok(clean(game));
|
|
assert.deepEqual(inventory(game),base.originalCards);
|
|
return {...base,game};
|
|
}
|
|
function declare(f:ReturnType<typeof fixture>):Game {
|
|
let game = act(f.game,f.asker,{type:'card',card:f.truths[0]});
|
|
while (game.truthtrance?.stage === 'priority') {
|
|
const actor = game.players.find(player => !game.truthtrance!.passed.includes(player.id)); assert.ok(actor);
|
|
game = act(game,actor.id,{type:'truthPass'});
|
|
}
|
|
assert.equal(game.truthtrance?.stage,'ask'); return game;
|
|
}
|
|
|
|
for (const phase of [0,1] as const) void test(
|
|
`Advanced phase ${phase} presents the upcoming Charity question and private guidance`, () => {
|
|
const f = fixture(phase), declared = declare(f), asker = viewGame(declared,f.asker);
|
|
const questionMarkup = renderToStaticMarkup(createElement(Truthtrance,{game:asker,busy:false,act() {}}));
|
|
assert.ok(asker.truthCharityTargets.includes(f.target));
|
|
assert.match(questionMarkup,/<option value="charity">[^<]*[Cc]harity/);
|
|
const asked = act(declared,f.asker,{type:'truthAsk',question:{kind:'charity',target:f.target,turn:declared.turn}});
|
|
const target = viewGame(asked,f.target);
|
|
assert.ok(target.truthCharityAnswers?.includes('yes'));
|
|
assert.ok(target.truthCharityAnswers?.includes('no'));
|
|
assert.equal(viewGame(asked,f.asker).truthCharityAnswers,null);
|
|
assert.equal(viewGame(asked,f.observer).truthCharityAnswers,null);
|
|
const bound = act(asked,f.target,{type:'truthAnswer',answer:'yes'});
|
|
const own = viewGame(bound,f.target), observer = viewGame(bound,f.observer);
|
|
assert.deepEqual(bound.ready,asked.ready);
|
|
assert.equal(own.truthCharityGuide,null);
|
|
assert.ok(own.truthCharityPromises.some(promise => promise.answer && !promise.fulfilled && !promise.released));
|
|
const markup = renderToStaticMarkup(createElement(TruthCharityPromise,
|
|
{game:own,busy:false,send() { assert.fail('Rendering must not send.'); }}));
|
|
assert.match(markup,/upcoming Charity phase/);
|
|
assert.match(markup,/Charity has not opened yet/);
|
|
assert.doesNotMatch(markup,/data-testid="charity-promise-guide"/);
|
|
assert.equal(observer.truthCharityPromises.length,0);
|
|
assert.equal(observer.truthCharityGuide,null);
|
|
assert.deepEqual(inventory(bound),f.originalCards);
|
|
},
|
|
);
|