Files
Gacy-Srtool/tests/mode-capabilities.test.cjs
T

131 lines
6.8 KiB
JavaScript
Raw Normal View History

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { pathToFileURL } = require('node:url');
const modesUrl = pathToFileURL(path.join(__dirname, '../js/modes.js'));
async function load() {
return import(modesUrl.href);
}
test('GaCy GO keeps every tool feature', async () => {
const { modeCapabilities } = await load();
const caps = modeCapabilities('gac');
for (const feature of [
'saveManager', 'exranks', 'inventory', 'monsterSettings', 'damageAnalyst',
'sceneCard', 'gmConsole', 'battleSummary', 'toolSession'
]) {
assert.equal(caps[feature], true, `${feature} must be available on GaCy GO`);
}
2026-11-04 17:14:50 +07:00
assert.equal(caps.fireflyEndgame, false);
assert.equal(caps.extraData, false);
assert.equal(caps.ownedAvatarsOnly, false);
assert.deepEqual(caps.jsonModes, ['freesr', 'persistent']);
});
test('FireflyGo hides every GaCy-only feature and exposes extra_data', async () => {
const { modeCapabilities, modeSupports } = await load();
const caps = modeCapabilities('firefly');
for (const feature of [
'saveManager', 'exranks', 'inventory', 'monsterSettings', 'damageAnalyst',
'sceneCard', 'gmConsole', 'battleSummary', 'toolSession'
]) {
assert.equal(caps[feature], false, `${feature} must be hidden on FireflyGo`);
}
assert.equal(caps.extraData, true);
2026-11-04 17:14:50 +07:00
assert.equal(caps.fireflyEndgame, true);
assert.equal(caps.ownedAvatarsOnly, true);
assert.deepEqual(caps.jsonModes, ['freesr']);
assert.equal(modeSupports('extraData', 'firefly'), true);
2026-11-04 17:14:50 +07:00
assert.equal(modeSupports('fireflyEndgame', 'firefly'), true);
assert.equal(modeSupports('monsterSettings', 'firefly'), false);
assert.equal(modeSupports('fireflyEndgame', 'gac'), false);
assert.equal(modeSupports('fireflyEndgame', 'robin'), false);
});
test('unknown modes fall back to GaCy GO', async () => {
const { normalizeMode, modeCapabilities, modeSupports, MODE_LABELS } = await load();
assert.equal(normalizeMode('nope'), 'gac');
assert.equal(normalizeMode(undefined), 'gac');
assert.equal(normalizeMode('firefly'), 'firefly');
assert.deepEqual(modeCapabilities('legacy'), modeCapabilities('gac'));
assert.equal(modeSupports('inventory', 'legacy'), true);
assert.equal(MODE_LABELS.firefly, 'FireflyGo');
});
test('mode UI strings exist in Thai and English', async () => {
const { TRANSLATIONS } = await import('../js/i18n.js');
const keys = [
'serverModeFirefly',
'apiUrlHintGaC', 'apiUrlHintFirefly', 'apiUrlHintRobin',
'enkaImportTitle', 'enkaImportSubtitle', 'enkaUidLabel', 'enkaUidPlaceholder',
'enkaUidInvalid', 'enkaModeMerge', 'enkaModeReplace', 'btnEnkaFetch',
'enkaPasteLabel', 'enkaPastePlaceholder', 'btnEnkaParsePaste',
'enkaFetching', 'enkaImportDone', 'enkaUidNotFound', 'enkaRateLimited',
'enkaFetchFailed', 'enkaFetchFailedDetail', 'enkaNoAvatars', 'enkaPasteEmpty',
'enkaPasteInvalid', 'enkaProxyUnavailable', 'enkaSyncFailed',
'fireflyExtrasTitle', 'fireflyExtrasBadge', 'fireflyExtrasSubtitle',
'fireflyMultiPathTitle', 'fireflyMultiPathMain', 'fireflyMultiPathMarch7',
'fireflyMultiPathMainList', 'fireflyMultiPathMarch7List',
'fireflySettingTitle', 'fireflySettingCensorship', 'fireflySettingCm',
'fireflySettingFirstPerson', 'fireflySettingHideUi', 'fireflySettingInvasion',
'fireflyChallengeTitle', 'fireflyChallengeSkipNode', 'fireflyChallengeGroupId',
'fireflyChallengeGroupList', 'fireflyTheoryTitle', 'fireflyTheoryMode',
'fireflyTheoryCycleCount', 'fireflyTheoryStageId', 'fireflyTheoryLineup',
'fireflyTheoryHp', 'fireflyLuaLabel', 'fireflyLuaPlaceholder', 'fireflyListPlaceholder',
'btnFireflyProbe', 'btnFireflySaveExtra', 'btnFireflySync',
'fireflyProbing', 'fireflySyncing', 'fireflyProbeSuccess', 'fireflySyncSuccess',
'fireflyRequestFailed', 'fireflyRequestFailedDetail', 'fireflyTimeout',
2026-11-04 17:14:50 +07:00
'fireflyNoData', 'fireflyExtraSaved', 'fireflyHpInvalid',
'ffEndgameTitle', 'ffEndgameTablistLabel', 'ffEndgameDescription', 'ffEndgameRule', 'ffEndgameModePeak',
'ffEndgameLoading', 'ffEndgameReady', 'ffEndgameCatalogError', 'ffEndgameSeason',
'ffEndgameFloor', 'ffEndgameFloorValue', 'ffEndgameSide', 'ffEndgameSideFirst',
'ffEndgameSideSecond', 'ffEndgameSideThird', 'ffEndgameStage', 'ffEndgameStageValue',
'ffEndgameStageKindPre', 'ffEndgameStageKindBoss', 'ffEndgameStageKindHard',
'ffEndgameStageId', 'ffEndgamePreview', 'ffEndgameNoStages', 'ffEndgameUseCycle',
'ffEndgameUseBuff', 'ffEndgameCycles', 'ffEndgameBlessings', 'ffEndgameMonsterCount',
'ffEndgameApply', 'ffEndgameApplySync', 'ffEndgameReset', 'ffEndgameResetDone',
'ffEndgameSaving', 'ffEndgameSaved', 'ffEndgameSynced', 'ffEndgameApplyError',
'ffEndgameNoData', 'ffEndgameSyncError', 'ffEndgameCustomDescription',
'ffEndgameAddWave', 'ffEndgameRemoveWave', 'ffEndgameAddMonster',
'ffEndgameRemoveMonster', 'ffEndgameMonsterId', 'ffEndgameMonsterLevel',
'ffEndgameMonsterAmount', 'ffEndgameCycleCount'
];
for (const lang of ['th', 'en']) {
for (const key of keys) {
const value = TRANSLATIONS[lang]?.[key];
assert.equal(typeof value, 'string', `${lang}.${key} must be a string`);
assert.ok(value.trim().length > 0, `${lang}.${key} must not be empty`);
assert.notEqual(value, key, `${lang}.${key} must be translated`);
}
}
});
test('the removed paused notice is no longer referenced', () => {
const app = fs.readFileSync(path.join(__dirname, '../js/app.js'), 'utf8');
assert.equal(app.includes('serverModesPausedNotice'), false);
});
test('mode-gated DOM hooks exist in index.html', () => {
const html = fs.readFileSync(path.join(__dirname, '../index.html'), 'utf8');
for (const id of [
'tab-btn-inventory', 'tab-btn-monster-settings', 'tab-btn-persistent', 'tab-btn-exrank',
'card-lineup', 'card-server-status', 'card-firefly-extras', 'api-url-mode-hint',
'enka-uid-input', 'enka-import-mode', 'btn-enka-fetch', 'enka-import-status',
'enka-paste-input', 'btn-enka-paste',
'ff-multi-path-main', 'ff-multi-path-march7', 'ff-multi-path-main-list',
'ff-multi-path-march7-list', 'ff-setting-censorship', 'ff-setting-cm',
'ff-setting-first-person', 'ff-setting-hide-ui', 'ff-setting-invasion-percent',
'ff-challenge-skip-node', 'ff-challenge-peak-group', 'ff-challenge-peak-list',
'ff-theory-mode', 'ff-theory-cycle-count', 'ff-theory-stage-id', 'ff-theory-lineup',
'ff-theory-hp', 'ff-lua', 'btn-firefly-probe', 'btn-firefly-save-extra',
2026-11-04 17:14:50 +07:00
'btn-firefly-sync', 'firefly-extra-status',
'monster-settings-gac', 'monster-settings-firefly', 'ff-endgame-tabs',
'ff-endgame-status', 'ff-endgame-view', 'ff-endgame-reset',
'ff-endgame-apply', 'ff-endgame-apply-sync'
]) {
assert.ok(html.includes(`id="${id}"`), `index.html must contain #${id}`);
}
});