feedback7 G-UI: reselecting the same operator keeps its draft skill and module (PR #306 by @Xinglan233)

Applied as-is. Clicking the operator already in the 自选 draft no longer rebuilds the draft from the saved pick or the default, so an in-progress skill or module edit stays. Choosing a different operator still loads that operator's saved pick or defaultPick.

Tests: node --test test/ui/diy-ui.test.js test/ui/feedback5-module-trait.test.js test/ui/diy.e2e.test.js — 25 pass, 0 fail. The diy.e2e suites skipped because SP_E2E is unset.
This commit is contained in:
Xinglan233 authored and sganggs committed 2026-10-08 18:41:36 +08:00
1 parent ae22335cfe
commit 25bcdff3a7
3 files changed
+130 -1

No files matched your search

+44
View File
@@ -197,6 +197,50 @@ test('diy sync: welcome brings the kit list and sends room.diy; edits are deboun
// ---- the tab --------------------------------------------------------------------------------------------------------------
describe('自选编队 tab (screens/diy.js)', () => {
for (const slotId of [T5A, T6A]) {
for (const saved of [null, SIEGE_PICK]) {
test(`the picker: ${slotId}, ${saved ? 'saved' : 'empty'} slot retains edits when reselecting its operator`, () => {
const picks = saved ? { [slotId]: saved } : {};
const done = [];
let draft = saved ? { ...saved } : null;
let filter = 'all';
let query = '';
const view = () => expand(DiyPickerView({ m: null, slot: { slotId }, picks, kitted: KIT,
onDone: (p) => done.push(p), onClose() {}, filter, query, draft,
onFilter: (f) => { filter = f; }, onQuery: (q) => { query = q; }, onDraft: (d) => { draft = d; } }));
const click = (key, value) => {
const node = [...walk(view())].find((v) => v.props?.[key] === value && typeof v.props.onClick === 'function');
assert.ok(node, `${key}=${value} is clickable`);
node.props.onClick();
};
click('data-char', SIEGE);
click('data-skill', 0);
click('data-module', 'none');
const edited = { charId: SIEGE, skillIndex: 0, uniEquipId: null };
assert.deepEqual(draft, edited);
click('data-char', SIEGE);
assert.deepEqual(draft, edited, 'reselecting keeps both the skill and explicit no-module choice');
// Filtering/searching the operator out and back in must not change the draft either.
filter = 'owned';
query = 'no matching operator';
assert.ok(![...walk(view())].some((v) => hasClass(v, 'diy-opt')));
query = '推进';
click('data-char', SIEGE);
assert.deepEqual(draft, edited);
click('data-testid', 'diy-confirm');
assert.deepEqual(done, [edited]);
assert.deepEqual(picks, saved ? { [slotId]: saved } : {}, 'the saved picks stay unchanged until the parent saves');
// Switching operators still initializes the new pick, and returning restores the saved/default pick.
filter = 'all';
query = '';
click('data-char', SHARP);
assert.deepEqual(draft, M.defaultPick(SHARP, slotId, D));
click('data-char', SIEGE);
assert.deepEqual(draft, saved || M.defaultPick(SIEGE, slotId, D));
});
}
}
test('four slots by tier: an empty slot to fill, a filled one shows the operator, its tag, skill and module', () => {
const tree = expand(DiyPanelView({ m: data.get('assets'), picks: { [T5A]: SIEGE_PICK, [T6A]: { charId: SHARP } }, legal: { [T5A]: SIEGE_PICK, [T6A]: { charId: SHARP } }, kitted: KIT, onSet() {}, picking: null, onPicking() {} }));
const slots = [...walk(tree)].filter((v) => hasClass(v, 'diy-slot'));