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, selectedDiscoveryLeaderSkillsProfile } from '../game/discovery-module-profile';
|
|
import { selectedDiscoveryWithoutCardsProfile, type FactionModuleProfile } from '../game/faction-module-profile';
|
|
import { advancedMoritaniLeaderSkillsProfile, basicMoritaniLeaderSkillsProfile,
|
|
nativeDiscoveryLeaderSkillsProfile, nativeEcazLeaderSkillsProfile,
|
|
ordinaryLeaderSkillModeSupported, strongholdLeaderSkillsProfile } from '../game/leader-skill-profile';
|
|
|
|
const base: FactionModuleProfile = {
|
|
advanced: false,
|
|
expansions: ['ix', 'choam', 'ecaz'],
|
|
players: [{faction:'atreides'}, {faction:'guild'}, {faction:'emperor'}],
|
|
discoveryEnabled: true,
|
|
leaderSkills: {},
|
|
};
|
|
|
|
void test('selected Discovery and Skills use the shared registered roster without requiring native seats', () => {
|
|
const rows: FactionModuleProfile[] = [
|
|
base,
|
|
{...base, advanced:true},
|
|
{...base, expansions:['ecaz'], players:[{faction:'atreides'}, {faction:'guild'}]},
|
|
{...base, expansions:['ix', 'ecaz'], players:[{faction:'ixians'}, {faction:'guild'}]},
|
|
{...base, players:[{faction:'ixians'}, {faction:'ecaz'}, {faction:'moritani'}]},
|
|
{...base, players:[{faction:'ixians'}, {faction:'ecaz'}, {faction:'guild'}],
|
|
discoveries:{}, discoveryStash:{}, greatMaker:{}, 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'}]},
|
|
];
|
|
for (const row of rows) {
|
|
const label = JSON.stringify(row);
|
|
assert.equal(selectedDiscoveryWithoutCardsProfile(row), true, label);
|
|
assert.equal(selectedDiscoveryLeaderSkillsProfile(row), true, label);
|
|
assert.equal(discoveryModeSupported(row), true, label);
|
|
assert.equal(nativeDiscoveryLeaderSkillsProfile(row), true, label);
|
|
assert.equal(ordinaryLeaderSkillModeSupported(row), true, label);
|
|
assert.equal(bureaucratPaymentModeSupported(row), true, label);
|
|
}
|
|
// The pre-deal lobby has not allocated the physical Skills deck yet.
|
|
const lobby: FactionModuleProfile = {...base, leaderSkills:undefined};
|
|
assert.equal(selectedDiscoveryLeaderSkillsProfile(lobby), true);
|
|
assert.equal(strongholdLeaderSkillsProfile({...base, advanced:true, strongholdCards:{}}), true);
|
|
});
|
|
|
|
void test('selected Discovery Skills preserve native Ecaz and Moritani participation', () => {
|
|
const pair = {...base, players:[{faction:'ecaz'}, {faction:'moritani'}, {faction:'guild'}]};
|
|
assert.equal(nativeEcazLeaderSkillsProfile(pair), true);
|
|
assert.equal(basicMoritaniLeaderSkillsProfile(pair), true);
|
|
assert.equal(advancedMoritaniLeaderSkillsProfile(pair), false);
|
|
const advanced = {...pair, advanced:true, moritaniAssassinatePreview:true};
|
|
assert.equal(nativeEcazLeaderSkillsProfile(advanced), true);
|
|
assert.equal(advancedMoritaniLeaderSkillsProfile(advanced), true);
|
|
});
|
|
|
|
void test('selected Discovery Skills reject illegal seats, decks, overlays and phase-module prerequisites', () => {
|
|
const rejected: FactionModuleProfile[] = [
|
|
{...base, discoveryEnabled:false},
|
|
{...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, nexusCards:{}},
|
|
{...base, ecazTreachery:true},
|
|
{...base, semutaPreview:true},
|
|
{...base, kullPreview:true},
|
|
{...base, nexusKullPreview:true},
|
|
{...base, guildBetrayalPreview:true},
|
|
{...base, nexusIxianBetrayalPreview:true},
|
|
{...base, moritaniAssassinatePreview:true},
|
|
];
|
|
for (const row of rejected) {
|
|
const label = JSON.stringify(row);
|
|
assert.equal(selectedDiscoveryWithoutCardsProfile(row), false, label);
|
|
assert.equal(selectedDiscoveryLeaderSkillsProfile(row), false, label);
|
|
}
|
|
});
|
|
|
|
void test('Advanced trained Harkonnen with actual E3 native remains excluded', () => {
|
|
for (const faction of ['ecaz', 'moritani']) {
|
|
const players = [{faction:'harkonnen'}, {faction}];
|
|
assert.equal(selectedDiscoveryLeaderSkillsProfile({...base, players}), true, faction);
|
|
assert.equal(selectedDiscoveryLeaderSkillsProfile({...base, players, advanced:true}), false, faction);
|
|
assert.equal(discoveryModeSupported({...base, players, advanced:true}), false, faction);
|
|
}
|
|
});
|