Files
Dune/tests/coalition-admission-bribe-controls.test.tsx
T
Quintine 6524ed3bf2
Verify and publish checkpoint container / container (push) Canceled after 0s
Allow group admission with compatible commitments
2026-10-29 00:54:36 +11:00

70 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 { CoalitionNexus, coalitionNexusOptions, type CoalitionNexusView } from '../components/coalition-nexus';
import type { CoalitionGroup } from '../game/coalition-alliance';
const players = ['a', 'b', 'c', 'd', 'e'].map(id => ({id, name: id.toUpperCase()}));
const group: CoalitionGroup = {id: 'group', members: ['a', 'b', 'c'], formedTurn: 1, edges: [
{members: ['a', 'b'], formedTurn: 1}, {members: ['a', 'c'], formedTurn: 1},
{members: ['b', 'c'], formedTurn: 1},
]};
const view = (me: string): CoalitionNexusView => ({
me, players, groups: [group], proposal: null, revision: 3, variant: 'unlimited',
});
const render = (value: CoalitionNexusView) => renderToStaticMarkup(createElement(CoalitionNexus, {
view: value, onIntent() {},
}));
void test('only the specified group and entrant invitation is blocked', () => {
const member = view('a');
member.blockedInvitations = [{groupId: 'group', entrant: 'd'}, {groupId: 'other', entrant: 'e'}];
const choices = coalitionNexusOptions(member);
assert.deepEqual(choices.invitations.map(row => row.entrant), ['e']);
assert.equal(choices.mayLeave, true);
const html = render(member);
assert.doesNotMatch(html, /Invite D to/);
assert.match(html, /Invite E to A, B, C/);
assert.match(html, /conflict with your commitments/);
assert.match(html, /Leave A, B, C/);
const entrant = view('d');
entrant.blockedInvitations = [{groupId: 'group', entrant: 'e'}];
assert.match(render(entrant), /Ask to join A, B, C/);
entrant.blockedInvitations = [{groupId: 'group', entrant: 'd'}];
assert.doesNotMatch(render(entrant), /Ask to join/);
});
void test('a blocked pending acceptance can still be declined or withdrawn', () => {
const pending = view('d');
pending.proposal = {event: 'event', nexus: 'nexus', turn: 2, groupId: group.id,
original: group, entrant: 'd', proposer: 'a', approvals: ['a', 'b']};
pending.acceptBlocked = true;
assert.equal(coalitionNexusOptions(pending).mayAccept, false);
assert.equal(coalitionNexusOptions(pending).mayDecline, true);
assert.doesNotMatch(render(pending), /Accept invitation/);
assert.match(render(pending), /conflict with your commitments/);
assert.match(render(pending), /Decline and cancel invitation/);
pending.me = 'b';
assert.match(render(pending), /Withdraw approval and cancel invitation/);
pending.me = 'd';
pending.acceptBlocked = false;
assert.equal(coalitionNexusOptions(pending).mayAccept, true);
assert.match(render(pending), /Accept invitation/);
});
void test('legacy admissionBlocked still blocks all invitations and acceptance', () => {
const member = view('a');
member.admissionBlocked = true;
assert.deepEqual(coalitionNexusOptions(member).invitations, []);
assert.equal(coalitionNexusOptions(member).mayLeave, true);
const pending = view('d');
pending.admissionBlocked = true;
pending.proposal = {event: 'event', nexus: 'nexus', turn: 2, groupId: group.id,
original: group, entrant: 'd', proposer: 'a', approvals: ['a']};
assert.equal(coalitionNexusOptions(pending).mayAccept, false);
assert.equal(coalitionNexusOptions(pending).mayDecline, true);
});