93 lines
4.8 KiB
TypeScript
93 lines
4.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { bureaucratPaymentModeSupported } from '../game/bureaucrat-payment';
|
|
import { discoveryModeSupported } from '../game/discovery-module-profile';
|
|
import { nexusCoreProfile, selectedNexusWithoutCardsProfile, type FactionModuleProfile } from '../game/faction-module-profile';
|
|
import { nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile,
|
|
ordinaryLeaderSkillModeSupported, selectedNexusLeaderSkillsProfile } from '../game/leader-skill-profile';
|
|
|
|
const base: FactionModuleProfile = {
|
|
advanced: false,
|
|
expansions: ['ix', 'choam', 'ecaz'],
|
|
players: [{ faction: 'atreides' }, { faction: 'guild' }, { faction: 'emperor' }],
|
|
nexusCards: {},
|
|
leaderSkills: {},
|
|
};
|
|
|
|
void test('selected Nexus Skills reuse ordinary Skills, Bureaucrat and Nexus rules with unused families', () => {
|
|
const rows: FactionModuleProfile[] = [
|
|
base,
|
|
{ ...base, advanced: true },
|
|
{ ...base, players: [{ faction: 'ixians' }, { faction: 'ecaz' }, { faction: 'guild' }],
|
|
nexusIxianBetrayalPreview: true, ecazOccupyPreview: true },
|
|
{ ...base, advanced: true, players: [{ faction: 'moritani' }, { faction: 'atreides' }, { faction: 'guild' }],
|
|
moritaniAssassinatePreview: true },
|
|
{ ...base, advanced: true, homeworlds: {}, techTokens: {}, strongholdCards: {} },
|
|
{ ...base, advanced: true, players: [{ faction: 'harkonnen' }, { faction: 'ixians' }],
|
|
nexusIxianBetrayalPreview: true },
|
|
];
|
|
for (const row of rows) {
|
|
const label = JSON.stringify(row);
|
|
assert.equal(selectedNexusWithoutCardsProfile(row), true, label);
|
|
assert.equal(nexusCoreProfile(row), true, label);
|
|
assert.equal(selectedNexusLeaderSkillsProfile(row), true, label);
|
|
assert.equal(nativeExpansionLeaderSkillsProfile(row), true, label);
|
|
assert.equal(ordinaryLeaderSkillModeSupported(row), true, label);
|
|
assert.equal(bureaucratPaymentModeSupported(row), true, label);
|
|
}
|
|
});
|
|
|
|
void test('selected Nexus Skills Discovery requires selection and survives live original token frames', () => {
|
|
assert.equal(discoveryModeSupported(base), false);
|
|
assert.equal(nativeDiscoveryLeaderSkillsProfile(base), false);
|
|
const enabled: FactionModuleProfile = { ...base, discoveryEnabled: true };
|
|
for (const row of [enabled, { ...enabled, discoveries: {}, discoveryStash: {}, greatMaker: {} }]) {
|
|
assert.equal(selectedNexusLeaderSkillsProfile(row), true);
|
|
assert.equal(discoveryModeSupported(row), true);
|
|
assert.equal(nativeDiscoveryLeaderSkillsProfile(row), true);
|
|
assert.equal(ordinaryLeaderSkillModeSupported(row), true);
|
|
assert.equal(bureaucratPaymentModeSupported(row), true);
|
|
}
|
|
assert.equal(selectedNexusWithoutCardsProfile({ ...base, discoveries: {} }), false);
|
|
assert.equal(discoveryModeSupported({ ...base, discoveries: {} }), false);
|
|
});
|
|
|
|
void test('selected Nexus Skills respect physical seat, family, optional-module and stamp boundaries', () => {
|
|
const rejected: FactionModuleProfile[] = [
|
|
{ ...base, nexusCards: undefined },
|
|
{ ...base, expansions: [] },
|
|
{ ...base, expansions: ['ix', 'ix'] },
|
|
{ ...base, expansions: ['ix', 'unknown'] },
|
|
{ ...base, players: [{ faction: 'atreides' }] },
|
|
{ ...base, players: [{ faction: 'atreides' }, { faction: 'atreides' }] },
|
|
{ ...base, players: [{ faction: 'atreides' }, { faction: 'unknown' }] },
|
|
{ ...base, expansions: ['ix'], players: [{ faction: 'choam' }, { faction: 'atreides' }] },
|
|
{ ...base, players: [{ faction: 'atreides' }, { faction: 'guild' }], techTokens: {} },
|
|
{ ...base, strongholdCards: {} },
|
|
{ ...base, ecazTreachery: true },
|
|
{ ...base, semutaPreview: true },
|
|
{ ...base, kullPreview: true },
|
|
{ ...base, nexusKullPreview: true },
|
|
{ ...base, nexusIxianBetrayalPreview: true },
|
|
{ ...base, moritaniAssassinatePreview: true },
|
|
];
|
|
for (const row of rejected) {
|
|
const label = JSON.stringify(row);
|
|
assert.equal(selectedNexusWithoutCardsProfile(row), false, label);
|
|
assert.equal(selectedNexusLeaderSkillsProfile(row), false, label);
|
|
}
|
|
});
|
|
|
|
void test('Advanced Harkonnen with an actual E3 native remains excluded, but unused E3 is permitted', () => {
|
|
for (const faction of ['ecaz', 'moritani']) {
|
|
const players = [{ faction: 'harkonnen' }, { faction }];
|
|
const basic = { ...base, players }, advanced = { ...basic, advanced: true };
|
|
assert.equal(selectedNexusLeaderSkillsProfile(basic), true, faction);
|
|
assert.equal(selectedNexusLeaderSkillsProfile(advanced), false, faction);
|
|
assert.equal(discoveryModeSupported({ ...advanced, discoveryEnabled: true }), false, faction);
|
|
}
|
|
const noE3Seat = { ...base, advanced: true, players: [{ faction: 'harkonnen' }, { faction: 'ixians' }] };
|
|
assert.equal(selectedNexusLeaderSkillsProfile(noE3Seat), true);
|
|
assert.equal(bureaucratPaymentModeSupported(noE3Seat), true);
|
|
});
|