80 lines
3.8 KiB
TypeScript
80 lines
3.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { createElement } from 'react';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { CoalitionFunding, coalitionFundingContributions, coalitionPledgeAction,
|
|
type CoalitionFundingView } from '../components/coalition-funding';
|
|
|
|
const view: CoalitionFundingView = {
|
|
targets: [
|
|
{ id: 'b', name: 'Emperor', pledged: 2, maximum: 6 },
|
|
{ id: 'c', name: 'Fremen', pledged: 1, maximum: 5 },
|
|
],
|
|
incoming: [
|
|
{ donor: 'b', name: 'Emperor', amount: 3 },
|
|
{ donor: 'c', name: 'Fremen', amount: 2 },
|
|
],
|
|
blocked: null,
|
|
};
|
|
|
|
void test('each outgoing ally has a separate labelled pledge and incoming amount', () => {
|
|
const html = renderToStaticMarkup(createElement(CoalitionFunding, {
|
|
view, act() {}, onContributionsChange() {},
|
|
}));
|
|
assert.match(html, /Pledge to Emperor · 2 spice currently set aside/);
|
|
assert.match(html, /Pledge to Fremen · 1 spice currently set aside/);
|
|
assert.match(html, /Set funding for Emperor/);
|
|
assert.match(html, /Set funding for Fremen/);
|
|
assert.match(html, /Emperor: 3 spice/);
|
|
assert.match(html, /Fremen: 2 spice/);
|
|
assert.match(html, /Use from Emperor for your next shipment/);
|
|
assert.match(html, /Use from Fremen for your next shipment/);
|
|
const bidding = renderToStaticMarkup(createElement(CoalitionFunding, {
|
|
view, act() {}, onContributionsChange() {}, purpose: 'bid',
|
|
}));
|
|
assert.match(bidding, /Use from Emperor for your next bid/);
|
|
assert.match(bidding, /Use from Fremen for your next bid/);
|
|
assert.doesNotMatch(bidding, /for your next shipment/);
|
|
});
|
|
|
|
void test('pledge action uses the named recipient and validates whole, safe limits', () => {
|
|
const target = view.targets[0];
|
|
assert.deepEqual(coalitionPledgeAction(target, '6', null),
|
|
{ type: 'coalitionPledge', recipient: 'b', amount: 6 });
|
|
assert.deepEqual(coalitionPledgeAction(target, '0', null),
|
|
{ type: 'coalitionPledge', recipient: 'b', amount: 0 });
|
|
for (const invalid of ['', '-1', '1.5', '7', '01', '1e2', '9007199254740992'])
|
|
assert.equal(coalitionPledgeAction(target, invalid, null), null);
|
|
assert.equal(coalitionPledgeAction(target, '2', 'Finish the pending payment.'), null);
|
|
assert.equal(coalitionPledgeAction(target, '2', null, true), null);
|
|
const committed = {...target, minimum: 2};
|
|
assert.equal(coalitionPledgeAction(committed, '1', null), null);
|
|
assert.deepEqual(coalitionPledgeAction(committed, '2', null),
|
|
{type: 'coalitionPledge', recipient: 'b', amount: 2});
|
|
const html = renderToStaticMarkup(createElement(CoalitionFunding, {
|
|
view:{...view, targets:[committed]}, act() {}, purpose:'bid',
|
|
}));
|
|
assert.match(html, /The current high bid commits 2 spice of this pledge/);
|
|
assert.match(html, /min="2"/);
|
|
});
|
|
|
|
void test('shipment selections retain donor identity and clamp to live pledges', () => {
|
|
assert.deepEqual(coalitionFundingContributions(view.incoming, {b: 9, c: 1.9, missing: 8}), [
|
|
{ donor: 'b', amount: 3 }, { donor: 'c', amount: 1 },
|
|
]);
|
|
assert.deepEqual(coalitionFundingContributions(view.incoming, {b: -2, c: 0}), []);
|
|
assert.deepEqual(coalitionFundingContributions([{donor: 'b', name: 'Emperor', amount: 1}],
|
|
{b: 3, c: 2}), [{ donor: 'b', amount: 1 }]);
|
|
});
|
|
|
|
void test('busy or blocked controls cannot submit and omit shipment inputs when not requested', () => {
|
|
const blocked = renderToStaticMarkup(createElement(CoalitionFunding, {
|
|
view: {...view, blocked: 'Finish the pending payment.'}, act() {},
|
|
}));
|
|
assert.match(blocked, /Finish the pending payment/);
|
|
assert.match(blocked, /disabled=""[^>]*>Set funding for Emperor/);
|
|
assert.doesNotMatch(blocked, /Use from Emperor for your next shipment/);
|
|
const busy = renderToStaticMarkup(createElement(CoalitionFunding, { view, busy: true, act() {} }));
|
|
assert.match(busy, /disabled=""[^>]*>Set funding for Fremen/);
|
|
});
|