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'].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, admissionBlocked = false): CoalitionNexusView => ({ me, players, groups:[group], proposal:null, revision:3, variant:'unlimited', admissionBlocked, }); const render = (value:CoalitionNexusView) => renderToStaticMarkup(createElement(CoalitionNexus, { view:value, onIntent() {}, })); void test('a live bribe commitment hides new invitations while retaining the owned leave control', () => { const member = view('a', true), choices = coalitionNexusOptions(member), html = render(member); assert.deepEqual(choices.invitations, []); assert.equal(choices.mayLeave, true); assert.match(html, /Invitations are unavailable while a bribe commitment remains unresolved/); assert.match(html, /Leave A, B, C/); assert.doesNotMatch(html, /Invite D to/); const entrant = view('d', true); assert.deepEqual(coalitionNexusOptions(entrant).invitations, []); assert.equal(coalitionNexusOptions(entrant).mayLeave, false); assert.doesNotMatch(render(entrant), /Ask to join/); }); void test('invitations return after the block clears; a blocked pending offer can be declined', () => { const member = view('a'); assert.deepEqual(coalitionNexusOptions(member).invitations.map(row => row.entrant), ['d']); assert.match(render(member), /Invite D to A, B, C/); assert.doesNotMatch(render(member), /bribe commitment remains unresolved/); const pending = view('d', 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); assert.doesNotMatch(render(pending), /Accept invitation/); assert.match(render(pending), /may decline this invitation/); });