65 lines
3.8 KiB
TypeScript
65 lines
3.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
matchesShipment,
|
|
parseShipmentClaim,
|
|
parseShipmentExpression,
|
|
shipmentClaimDestinations,
|
|
shipmentClaimHasNoField,
|
|
shipmentClaimText,
|
|
ShipmentClaimError,
|
|
} from '../game/shipment-promises';
|
|
import { TERRITORIES } from '../game/board';
|
|
import { shipmentExpressionInputError, shipmentExpressionInputSize } from '../game/shipment-expression-input';
|
|
|
|
void test('a No-Field shipment statement keeps identity and denomination private', () => {
|
|
const wildcard = parseShipmentClaim({ claim: { kind: 'noField' } });
|
|
assert.deepEqual(wildcard, { claim: { kind: 'noField' } });
|
|
assert.equal(shipmentClaimHasNoField(wildcard), true);
|
|
assert.deepEqual(shipmentClaimDestinations(wildcard), TERRITORIES.map(t => t.id));
|
|
assert.equal(shipmentClaimText(wildcard), 'ship your No-Field from your reserves');
|
|
assert.equal(matchesShipment(wildcard, null), false);
|
|
assert.equal(matchesShipment(wildcard, { territory: 'carthag', sector: 11, amount: 1 }), false);
|
|
assert.equal(matchesShipment(wildcard, { territory: 'carthag', sector: 11, amount: 0, noField: true }), true);
|
|
assert.equal(shipmentExpressionInputError({ kind: 'noField' }), null);
|
|
assert.deepEqual(shipmentExpressionInputSize({ kind: 'noField' }), { leaves: 1, depth: 0 });
|
|
const target = parseShipmentClaim({ claim: { kind: 'noField', territory: 'carthag', sector: 11 } });
|
|
assert.deepEqual(shipmentClaimDestinations(target), ['carthag']);
|
|
assert.match(shipmentClaimText(target), /Carthag, sector 11/);
|
|
assert.equal(matchesShipment(target, { territory: 'carthag', sector: 11, amount: 0, noField: true }), true);
|
|
assert.equal(matchesShipment(target, { territory: 'carthag', sector: 10, amount: 0, noField: true }), false);
|
|
assert.equal(matchesShipment(target, { territory: 'arrakeen', sector: 10, amount: 0, noField: true }), false);
|
|
});
|
|
|
|
void test('No-Field and physical clauses constrain the same real shipment', () => {
|
|
const claim = parseShipmentClaim({ claim: { op: 'and', terms: [
|
|
{ kind: 'noField', territory: 'carthag' },
|
|
{ territory: 'carthag', minimum: 2 },
|
|
] } });
|
|
assert.equal(matchesShipment(claim, { territory: 'carthag', sector: 11, amount: 2, noField: true }), true);
|
|
assert.equal(matchesShipment(claim, { territory: 'carthag', sector: 11, amount: 1, noField: true }), false);
|
|
assert.equal(matchesShipment(claim, { territory: 'carthag', sector: 11, amount: 2 }), false);
|
|
assert.equal(matchesShipment(claim, null), false);
|
|
const old = parseShipmentClaim({ territory: 'carthag', minimum: 1 });
|
|
assert.equal(shipmentClaimHasNoField(old), false);
|
|
assert.equal(shipmentClaimHasNoField(claim), true);
|
|
assert.equal(matchesShipment(old, { territory: 'carthag', amount: 0, noField: true }), false);
|
|
assert.equal(matchesShipment(old, { territory: 'carthag', amount: 1 }), true);
|
|
const either = parseShipmentClaim({ claim: { op: 'or', terms: [
|
|
{ kind: 'noField' }, { territory: 'arrakeen', minimum: 3 },
|
|
] } });
|
|
assert.equal(matchesShipment(either, { territory: 'carthag', amount: 0, noField: true }), true);
|
|
assert.equal(matchesShipment(either, { territory: 'arrakeen', amount: 3 }), true);
|
|
assert.equal(matchesShipment(either, null), false);
|
|
});
|
|
|
|
void test('No-Field statements reject secret identifiers, invalid destinations and standalone sectors', () => {
|
|
for (const bad of [
|
|
{ kind: 'noField', token: 'secret' }, { kind: 'noField', value: 3 },
|
|
{ kind: 'noField', sector: 11 }, { kind: 'noField', territory: 'not-a-territory' },
|
|
{ kind: 'noField', territory: 'carthag', sector: 10 },
|
|
{ kind: 'noField', territory: 'carthag', minimum: 1 },
|
|
]) assert.throws(() => parseShipmentExpression(bad), ShipmentClaimError);
|
|
assert.match(shipmentExpressionInputError({ kind: 'noField', sector: 11 })!, /No-Field shipment/);
|
|
});
|