Files
Dune/tests/coalition-funding-controls.test.tsx
Quintine 1eeeb32566
Verify and publish checkpoint container / container (push) Successful in 10m27s
Support staged group bid funding
2026-10-28 23:22:50 +11:00

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/);
});