Files
Dune/tests/advisor-worm-ride-controls.test.tsx
T
Quintine c608d6fea6
Verify and publish checkpoint container / container (push) Canceled after 0s
Handle advisor conversion after worm rides
2026-10-29 09:10:53 +11:00

79 lines
3.7 KiB
TypeScript
Raw 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 { readFileSync } from 'node:fs';
import { registerHooks } from 'node:module';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { viewGame, type Game } from '../game/engine';
import { actAdvisorWormRide as act, advisorWormRidePlayer as player,
createAdvisorWormRideFixture as fixture } from './fixture-advisor-worm-ride-flip';
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 {GameTable} = await import('../components/game-table');
aliases.deregister();
/** Public setup is genuine; the fixture discloses its staged ride and conserved
* force placement. The real ride action opens the response under test. */
function response() {
const f = fixture();
const game = act(f.game,f.fremen,f.action);
assert.equal(game.response?.automaticAdvisorFlip?.producer,'wormRide');
return {...f,game};
}
function table(game:Game, player:string, busy = false) {
return renderToStaticMarkup(createElement(GameTable, {
game:viewGame(game,player), busy,
send:async () => { assert.fail('Rendering must not submit an action.'); },
onExit() { assert.fail('Rendering must not leave the table.'); },
}));
}
void test('the real worm-ride conversion explains its committed source to every seat', () => {
const f = response(), before = structuredClone(f.game);
for (const actor of [f.bg,f.fremen,f.holder]) {
const html = table(f.game,actor);
assert.match(html,/Bene Gesserit token flip/);
assert.match(html,/The worm ride and any collection are complete/);
assert.match(html,/advisors are now alone and must become fighters before the original arrival continues/);
assert.match(html,/Karama prevents only this conversion/);
}
assert.deepEqual(f.game,before);
});
void test('only the eligible holder sees native Karama and allowance controls', () => {
const f = response(), holder = viewGame(f.game,f.holder);
assert.ok(holder.responseControls?.cancelCards.includes(f.karama));
const html = table(f.game,f.holder);
assert.match(html,/Cancel with Karama/);
assert.match(html,/Allow this power/);
assert.doesNotMatch(table(f.game,f.bg),/Cancel with Karama/);
const busy = table(f.game,f.holder,true);
assert.match(busy,/<button(?=[^>]*disabled="")[^>]*>Cancel with Karama/);
});
void test('Fremen sees why summoning another worm waits for the current conversion', () => {
const f = fixture();
const holder = player(f.game,f.holder), fremen = player(f.game,f.fremen);
const index = holder.hand.findIndex(card => card.id === f.karama);
assert.ok(index >= 0 && fremen.hand.length > 0);
// Conserved physical-card swap before the actual ride gives Fremen Karama.
[holder.hand[index],fremen.hand[0]] = [fremen.hand[0],holder.hand[index]];
const game = act(f.game,f.fremen,f.action), before = structuredClone(game);
const html = table(game,f.fremen);
assert.match(html,/Resolve the completed worm ride’s advisor conversion before summoning another worm/);
assert.match(html,/<button(?=[^>]*disabled="")[^>]*>Spend Karama · summon Shai-Hulud/);
assert.throws(() => act(game,f.fremen,{type:'card',mode:'special',card:f.karama,territory:'hagga_basin'}));
assert.deepEqual(game,before);
});