76 lines
3.2 KiB
TypeScript
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), []);
|
|
}
|
|
});
|