Files
Dune/tests/selected-discovery-skills-profile.test.ts
T
Quintine 77eb2392eb
Verify and publish checkpoint container / container (push) Canceled after 0s
Support mixed Discovery decks with Leader Skills
2026-10-30 17:49:26 +11:00

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);
}
});