Files
Dune/tests/homeworld-return-native-controls.test.tsx
Quintine 89569e92a1
Verify and publish checkpoint container / container (push) Successful in 11m10s
Support Advanced native Homeworld return
2026-10-29 04:48:47 +11:00

71 lines
3.6 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import type { GameView } from '../game/engine';
import { HomeworldShipment } from '../components/homeworld-shipment';
import { homeworldShipmentChoice } from '../game/homeworld-shipment-options';
import { homeworldForceGroups, type HomeworldCustody } from '../game/homeworld-custody';
import { homeworldPopulations } from '../game/homeworld-population';
/** Personalized public view: the Atreides player has an actual physical
* foreign garrison. Native and foreign pools are projected using the same
* Homeworld helpers as the existing shipment-control fixture. */
function fixture(advanced: boolean): GameView {
const context = { advanced, players: [
{ id: 'a', faction: 'atreides' as const, reserves: 17, eliteReserves: 0, ally: null },
{ id: 'g', faction: 'guild' as const, reserves: 20, eliteReserves: 0, ally: null },
] };
const custody: HomeworldCustody = { salusa: null,
visitors: { 'homeworld:guild': { a: { normal: 3, elite: 0 } } } };
const populations = homeworldPopulations(context, custody);
return {
me: 'a', active: 'a', advanced, status: 'playing', phase: 5,
homeworldShipment: { event: 'shipment:1:a', blocked: null },
aid: { available: 0, pledged: 0 },
players: context.players.map(player => ({ ...player, name: player.faction,
spice: player.id === 'a' ? 10 : undefined, shipped: false,
elites: { reserves: player.eliteReserves } })),
homeworlds: { worlds: homeworldForceGroups(context, custody).map(world => ({
...world, ...populations.find(row => row.location === world.id)!,
})) },
} as unknown as GameView;
}
function markup(game: GameView): string {
return renderToStaticMarkup(createElement(HomeworldShipment, { game, busy: false, act() {} }));
}
function destinationOptions(html: string): string {
const options = /<select aria-label="Destination Homeworld"[^>]*>([\s\S]*?)<\/select>/.exec(html);
assert.ok(options, 'The native Homeworld shipment destination selector is present');
return options[1];
}
void test('Advanced personal shipment exposes the own Homeworld, source distinction and price', () => {
const game = fixture(true), before = structuredClone(game), html = markup(game);
const options = destinationOptions(html);
assert.match(options, /value="homeworld:atreides"[^>]*>Caladan · return to your Homeworld/);
assert.match(options, /value="homeworld:guild"/);
assert.match(html, /You may return a foreign garrison to your own Homeworld/);
assert.match(html, /Native reserves and foreign garrisons have separate source pools/);
assert.match(html, /Pay one spice per force/);
const quote = homeworldShipmentChoice(game, 'homeworld:atreides',
{ 'homeworld:guild': { normal: 2, elite: 0 } });
assert.equal(quote.blocked, null);
assert.equal(quote.cost, 2);
assert.equal(quote.action?.destination, 'homeworld:atreides');
assert.deepEqual(game, before);
});
void test('Basic personal shipment retains the explicit native destination restriction', () => {
const game = fixture(false), html = markup(game);
const options = destinationOptions(html);
assert.doesNotMatch(options, /value="homeworld:atreides"/);
assert.match(options, /value="homeworld:guild"/);
assert.match(html, /Your own Homeworld cannot be a destination/);
const quote = homeworldShipmentChoice(game, 'homeworld:atreides',
{ 'homeworld:guild': { normal: 2, elite: 0 } });
assert.equal(quote.action, null);
assert.match(quote.blocked ?? '', /Basic play.*own Homeworld/);
});