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):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,/