Files
Dune/tests/mixed-alliance-question.test.ts

52 lines
3.4 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { AlliancePromiseError } from '../game/alliance-promises';
import { parseAllianceActionClaim, type AllianceActionClaim, type MixedAllianceClaim } from '../game/mixed-alliance-question';
import { compileMixedActionExpression, parseMixedActionExpression } from '../game/mixed-action-question';
import type { TruthFact } from '../game/truthtrance';
void test('mixed alliance action leaves retain one exact partner without adding turn or private Nexus bindings', () => {
const input = Object.freeze({ partner: 'exact-partner-id' });
const parsed = parseAllianceActionClaim(input);
assert.deepEqual(parsed, input); assert.notEqual(parsed, input);
assert.deepEqual(parseAllianceActionClaim({ partner: 'asker-can-be-the-partner' }), { partner: 'asker-can-be-the-partner' });
});
void test('mixed alliance action leaves reject metadata, frozen values, groups and missing or inexact identities', () => {
const invalid: unknown[] = [null, undefined, [], 'partner-a', {}, { partner: '' }, { partner: ' ' },
{ partner: ' partner-a' }, { partner: 'partner-a ' }, { partner: 2 }, { partner: null },
{ partner: 'partner-a', turn: 1 }, { partner: 'partner-a', source: 'private' },
{ partner: 'partner-a', event: 'private' }, { partner: 'partner-a', answer: true },
{ partner: 'partner-a', fulfilled: false }, { kind: 'partner', partner: 'partner-a' },
{ kind: 'or', terms: [{ partner: 'partner-a' }, { partner: 'partner-b' }] }];
for (const value of invalid) assert.throws(() => parseAllianceActionClaim(value), AlliancePromiseError);
});
void test('shared mixed parsing rejects a malformed late alliance leaf before a decisive fact can hide it', () => {
const fact: TruthFact = { kind: 'spice', compare: 'gte', value: 10 };
const parseFact = (): TruthFact => fact;
const input = { kind: 'or', terms: [{ kind: 'fact', fact },
{ kind: 'action', action: { partner: 'partner-a' } }, { kind: 'action', action: { partner: 'partner-b', turn: 1 } }] };
assert.throws(() => parseMixedActionExpression(input, parseFact, parseAllianceActionClaim), AlliancePromiseError);
const valid = { kind: 'and', terms: [{ kind: 'fact', fact }, { kind: 'or', terms: [
{ kind: 'action', action: { partner: 'partner-a' } }, { kind: 'action', action: { partner: 'partner-b' } }] }] };
const parsed = parseMixedActionExpression(valid, parseFact, parseAllianceActionClaim);
assert.deepEqual(parsed, valid);
assert.deepEqual(compileMixedActionExpression(parsed, () => 'yes', true), valid.terms[1]);
});
void test('frozen current facts reduce only the residual final-partner expression and preserve raw mixed text', () => {
const question: MixedAllianceClaim = { turn: 2, mixed: { kind: 'or', terms: [
{ kind: 'fact', fact: { kind: 'spice', compare: 'gte', value: 10 } },
{ kind: 'and', terms: [{ kind: 'action', action: { partner: 'partner-a' } },
{ kind: 'action', action: { partner: 'partner-b' } }] },
] } };
const before = structuredClone(question);
assert.deepEqual(compileMixedActionExpression<AllianceActionClaim>(question.mixed, () => 'yes', true),
{ kind: 'constant', value: true });
assert.deepEqual(compileMixedActionExpression(question.mixed, () => 'no', false),
{ kind: 'and', terms: [{ kind: 'action', action: { partner: 'partner-a' } },
{ kind: 'action', action: { partner: 'partner-b' } }] });
assert.deepEqual(question, before);
});