Files
Dune/tests/diplomat-retreat-controls.test.tsx
T

76 lines
3.2 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createElement } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { DiplomatRetreat } from '../components/diplomat-retreat';
import { botActions } from '../game/bots';
import { DIFFICULTIES } from '../game/bot-profiles';
import { viewGame, type GameView } from '../game/engine';
import { diplomatDefenseGame } from './diplomat-defense-fixture';
function offeredView(viewer = 'a'): GameView {
const view = viewGame(diplomatDefenseGame(), viewer);
view.decision = {
kind: 'diplomatRetreat', player: 'a', event: 'retreat-event',
destinations: [
{ location: 'imperial_basin:9', choices: [
{ normal: 1, elite: 0 },
{ normal: 2, elite: 1 },
{ normal: 1, elite: 2 },
] },
{ location: 'hagga_basin:12', choices: [
{ normal: 0, elite: 1 },
{ normal: 1, elite: 1 },
] },
],
};
return view;
}
void test('only the deciding player can select every offered destination and physical count or decline', () => {
const view = offeredView();
const markup = (game: GameView, busy = false) => renderToStaticMarkup(
createElement(DiplomatRetreat, { game, act() {}, busy }),
);
const html = markup(view);
assert.match(html, /aria-label="Diplomat retreat choice"/);
assert.match(html, /Imperial Basin · sector 9/);
assert.match(html, /Hagga Basin · sector 12/);
assert.match(html, /2 ordinary · 1 elite/);
assert.match(html, /1 ordinary · 2 elite/);
assert.doesNotMatch(html, /0 ordinary · 1 elite/);
assert.match(html, /Retreat to Imperial Basin · sector 9/);
assert.match(html, /Decline Diplomat retreat/);
assert.equal(markup(offeredView('d')), '');
assert.equal((markup(view, true).match(/disabled=""/g) ?? []).length, 6);
if (view.decision?.kind !== 'diplomatRetreat') throw new Error('Expected Diplomat retreat');
view.decision.destinations.reverse();
const alternate = markup(view);
assert.match(alternate, /0 ordinary · 1 elite/);
assert.doesNotMatch(alternate, /2 ordinary · 1 elite/);
view.decision.destinations = [];
assert.match(markup(view), /No legal retreat destination and force combination/);
assert.doesNotMatch(markup(view), /Retreat to Imperial Basin/);
assert.match(markup(view), /Decline Diplomat retreat/);
});
void test('all bot profiles select the first destination and largest legal physical count, or decline if none', () => {
for (const difficulty of DIFFICULTIES) {
const view = offeredView();
view.players.find((player) => player.id === view.me)!.bot = difficulty;
assert.deepEqual(botActions(view)[0], {
type: 'decision', event: 'retreat-event',
destination: 'imperial_basin:9', normal: 2, elite: 1,
});
if (view.decision?.kind !== 'diplomatRetreat') throw new Error('Expected Diplomat retreat');
view.decision.destinations = [];
assert.deepEqual(botActions(view)[0], {
type: 'decision', event: 'retreat-event',
destination: null, normal: 0, elite: 0,
});
const observer = offeredView('d');
observer.players.find((player) => player.id === observer.me)!.bot = difficulty;
assert.deepEqual(botActions(observer), []);
}
});