feedback7 R22-LOADOUT: 干员调配's module card reads the module's talent changes at the operator's 潜能, as 局内数值 and the battle do; golden: unchanged

Grok's review of the branch (low): ModuleInfo read talentChanges from the data's module record — the full-potential one —
so at 潜能1 余's 闲云隐市 still read 「生命上限2%(+0.5%)」 while 局内数值 and the battle use 1.5 % (异客 +10 %(+2 %) vs
+8 %). ModuleInfo takes `potential` and composes the elite at it first (shared/potential.js atPotential; the module's
traitOverride does not depend on potential); the detail passes the operator's setting.

- Test: test/ui/loadout-rows.test.js — 余's module card at none / 潜能6 / 潜能1, 不装备's base 特性, the detail's prop.
This commit is contained in:
sganggs committed 2026-10-08 22:20:30 +08:00
1 parent 4f8f5d2acf
commit 9f36db32e8
2 files changed
+31 -5

No files matched your search

+19 -1
View File
@@ -15,7 +15,7 @@ globalThis.fetch = async (url) => {
const name = String(url).split('/').pop();
try { const body = readFileSync(path.join(ROOT, 'data', name), 'utf8'); return { ok: true, status: 200, json: async () => JSON.parse(body) }; } catch { return { ok: false, status: 404, json: async () => ({}) }; }
};
const { RosterRow, RosterHead, statsPreview, LoadoutStats } = await import('../../public/js/screens/loadout.js');
const { RosterRow, RosterHead, statsPreview, LoadoutStats, ModuleInfo } = await import('../../public/js/screens/loadout.js');
const { CultivationSelects, CultivationSection, cultivateName } = await import('../../public/js/screens/cultivation.js');
const { DiyPanelView } = await import('../../public/js/screens/diy.js');
const { data } = await import('../../public/js/data.js');
@@ -144,6 +144,24 @@ test('局内数值 at the operator\'s settings: 刺玫 at 潜能1 / 未精英化
assert.match(cap(LoadoutStats({ base: v, golden: g, entries: {}, level: 'elite', onLevel() {}, getChess: get, ops: {} })), /^数值含所选模组;含潜能与练度;不含技能发动/);
});
test('the module card reads its talent changes at the operator\'s 潜能, as 局内数值 and the battle do (余 闲云隐市: 2%(+0.5%) / 1.5%)', () => {
// (Grok review of the branch: the card printed the full-potential line whatever the setting)
const g = get('chess_char_6_03_b');
const mod = g.modules.find((x) => x.uniEquipId === 'uniequip_002_yu');
const opt = { id: mod.uniEquipId, rec: mod, isDefault: !!mod.isDefault };
const texts = (tree) => find(tree, (v) => typeof v.type === 'function' && v.type.name === 'RichText').map((v) => String(v.props.text));
const full = texts(ModuleInfo({ m: null, golden: g, opt }));
assert.ok(full.some((x) => x.includes('生命上限2%<@ba.talpu>(+0.5%)</>')), 'full potential (none given)');
assert.deepEqual(texts(ModuleInfo({ m: null, golden: g, opt, potential: 6 })), full);
const p1 = texts(ModuleInfo({ m: null, golden: g, opt, potential: 1 }));
assert.ok(p1.some((x) => x.includes('生命上限1.5%的生命')), '潜能1');
assert.ok(!p1.some((x) => x.includes('(+0.5%)')));
assert.deepEqual(texts(ModuleInfo({ m: null, golden: g, opt: { id: 'none', rec: null }, potential: 1 })), [g.traitBase.descRaw], '不装备: the base 特性');
// the detail hands the operator's 潜能 to it
const src = readFileSync(path.join(ROOT, 'public/js/screens/loadout.js'), 'utf8');
assert.match(src, /<\$\{ModuleInfo\} m=\$\{m\} golden=\$\{golden\} opt=\$\{modOpt\} potential=\$\{opsOf\(ops, chess\.charId\)\.potential\} \/>/);
});
test('css: the head and the rows share one grid (columns aligned), quick targets grow on a coarse pointer, the detail slides over below 1000 px', () => {
const css = readFileSync(path.join(ROOT, 'public/css/screens/loadout.css'), 'utf8');
assert.match(css, /\.lo-list__head, \.lo \.lo-card \{ display: grid; grid-template-columns: var\(--cols\);/);