49 lines
3.4 KiB
JavaScript
49 lines
3.4 KiB
JavaScript
// GitHub #538: a loadout file that carries `ops` (including `ops: {}`) replaces 潜能 / 练度. That list includes
|
|
// 自选 operators, which only backups.json names. Importing it while that file is missing used to drop them and still
|
|
// save, clearing a 练度 the file did not mean to erase. The whole import is refused first, with the 自选编队 data check.
|
|
// No browser: the refusal is a function, and ioApply must call it after a successful parse and before any write.
|
|
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
globalThis.fetch = async () => ({ ok: false, status: 404, json: async () => ({}) });
|
|
const warn = console.warn;
|
|
console.warn = (...a) => { if (!String(a[0]).startsWith('[data]')) warn(...a); };
|
|
|
|
const { loadoutOpsImportRefusal } = await import('../../public/js/screens/loadout.js');
|
|
|
|
const NOT_LOADED = '导入失败:游戏数据没有载入,未做任何改动。请刷新页面;仍不行时,请检查广告拦截插件和网络';
|
|
const LOADING = '干员数据仍在载入,请稍候再导入';
|
|
const statusOf = (map, dflt = 'ready') => (name) => map[name] ?? dflt;
|
|
|
|
test('a loadout ops payload is refused with the DIY data check; entries-only is not', () => {
|
|
const noBackups = statusOf({ backups: 'missing' });
|
|
const bothMissing = statusOf({ chess: 'missing', backups: 'missing' });
|
|
const ready = statusOf({});
|
|
assert.equal(loadoutOpsImportRefusal(null, true, noBackups), null, 'no ops key: current 练度 stays');
|
|
assert.equal(loadoutOpsImportRefusal(undefined, true, noBackups), null);
|
|
assert.deepEqual(loadoutOpsImportRefusal({}, true, noBackups), { text: NOT_LOADED, tone: 'error' }, 'ops: {} still replaces 练度');
|
|
assert.deepEqual(loadoutOpsImportRefusal({ char_112_siege: { potential: 1 } }, true, noBackups), { text: NOT_LOADED, tone: 'error' });
|
|
assert.deepEqual(loadoutOpsImportRefusal({ char_112_siege: { potential: 1 } }, true, bothMissing), { text: NOT_LOADED, tone: 'error' });
|
|
assert.deepEqual(loadoutOpsImportRefusal({}, false, ready), { text: LOADING, tone: 'warn' }, 'still loading: nothing is written');
|
|
assert.equal(loadoutOpsImportRefusal({ char_112_siege: { potential: 1 } }, true, ready), null, 'both files ready: the import may proceed');
|
|
assert.equal(loadoutOpsImportRefusal(null, false, noBackups), null, 'entries-only does not wait on backups');
|
|
});
|
|
|
|
test('ioApply asks loadoutOpsImportRefusal after parseImport and before cultivationCharIds or applyLoadoutEntries', () => {
|
|
const src = readFileSync(path.join(ROOT, 'public/js/screens/loadout.js'), 'utf8');
|
|
const at = src.indexOf('const ioApply = () => {');
|
|
assert.ok(at > 0, 'ioApply');
|
|
const body = src.slice(at, src.indexOf('\n };\n', at));
|
|
const parsed = body.indexOf('if (!res.ok)');
|
|
const guard = body.indexOf('loadoutOpsImportRefusal(res.ops, ready)');
|
|
const ids = body.indexOf('cultivationCharIds(');
|
|
const apply = body.indexOf('applyLoadoutEntries(');
|
|
assert.ok(parsed > 0 && guard > parsed, 'refuse only a payload that parsed');
|
|
assert.ok(ids > guard && apply > guard, 'no write and no DIY id list until the refusal returns null');
|
|
assert.match(body.slice(guard), /^loadoutOpsImportRefusal\(res\.ops, ready\);\s*if \(opsRefused\) \{ toast\(opsRefused\.text, opsRefused\.tone\); return; \}/);
|
|
});
|