feedback5 WE2: the briefing and the 本局信息 views name a 自选 piece the match leaves out of the shop (#11)
m.private.diyBanned (every bond of the operator off this match) is shown under 本局禁用干员 in the INFO_CHECK briefing, the strategy draft's 本局信息 dialog and the in-game 本局信息 tab: ui/gameLogic/diy.js diyBannedPieces, ui/matchInfo.js matchInfoModel diyBanned + DiyBannedLine (t() with English in public/i18n/en.json). Client only; golden unchanged.
This commit is contained in:
1 parent
7b83028139
commit
d31de31e31
13 files changed
+146
-17
No files matched your search
@@ -0,0 +1,70 @@
|
||||
// test/ui/feedback5-we2-diybanned.test.js — 0.2.0 WE2 #11: the player's own 自选 pieces left out of the shop because every
|
||||
// bond of the operator is switched off this match (m.private.diyBanned) are named under 本局禁用干员 — the briefing, the
|
||||
// strategy draft's 本局信息 dialog (ui/matchInfo.js) and the in-game 本局信息 tab (ui/enemyDrawer.js).
|
||||
// Run: node --test test/ui/feedback5-we2-diybanned.test.js
|
||||
|
||||
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 (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 G = await import('../../public/js/ui/gameLogic.js');
|
||||
const { matchInfoModel, DiyBannedLine } = await import('../../public/js/ui/matchInfo.js');
|
||||
const { data } = await import('../../public/js/data.js');
|
||||
const { setLang, addMessages } = await import('../../shared/i18n.js');
|
||||
const { DATA } = await import('../match/harness.js');
|
||||
await data.loadAll('chess', 'bonds', 'assets', 'backups');
|
||||
|
||||
const T5A = 'chess_char_5_diy1_a';
|
||||
const T6A = 'chess_char_6_diy1_a';
|
||||
const SIEGE = 'char_112_siege';
|
||||
const LING = 'char_2023_ling';
|
||||
const D = { chess: DATA.chess, backups: DATA.backups };
|
||||
const getChess = (id) => (Object.hasOwn(DATA.chess, id) ? DATA.chess[id] : null);
|
||||
const priv = {
|
||||
diy: { [T5A]: { charId: SIEGE, skillIndex: 2, uniEquipId: 'uniequip_002_siege' }, [T6A]: { charId: LING, skillIndex: 0, uniEquipId: null } },
|
||||
diyBanned: [T6A],
|
||||
};
|
||||
const textOf = (v) => (Array.isArray(v) ? v.map(textOf).join('') : v == null || typeof v === 'boolean' ? '' : typeof v === 'object' ? textOf(v.props?.children) : String(v));
|
||||
|
||||
test('#11 diyBannedPieces: the banned slots with their operator\'s name, slot order; none without picks', () => {
|
||||
assert.deepEqual(G.diyBannedPieces(priv, getChess, D), [{ slotId: T6A, charId: LING, name: DATA.backups.units[LING].name }]);
|
||||
assert.deepEqual(G.diyBannedPieces({ diy: priv.diy, diyBanned: [] }, getChess, D), []);
|
||||
assert.deepEqual(G.diyBannedPieces({ diyBanned: [T6A] }, getChess, D), [], 'no pick for the slot: nothing');
|
||||
assert.deepEqual(G.diyBannedPieces(null, getChess, D), []);
|
||||
});
|
||||
|
||||
test('#11 the match-info model and its line: the own banned 自选 piece is named; nothing without priv / diyBanned', () => {
|
||||
const pub = { bannedChess: [], drawnDisabledBonds: [], modeId: 'mode_multi_hard' };
|
||||
const model = matchInfoModel(pub, { bonds: [], chess: getChess, priv, diyData: D });
|
||||
assert.deepEqual(model.diyBanned.map((x) => x.slotId), [T6A]);
|
||||
setLang('zh');
|
||||
const line = DiyBannedLine({ model });
|
||||
assert.ok(line, 'a line');
|
||||
const txt = textOf(line);
|
||||
assert.ok(txt.includes('自选') && txt.includes(DATA.backups.units[LING].name) && txt.includes('不会出现在你的商店'), txt);
|
||||
assert.equal(DiyBannedLine({ model: matchInfoModel(pub, { bonds: [], chess: getChess }) }), null, 'no priv: no line');
|
||||
assert.equal(DiyBannedLine({ model: matchInfoModel(pub, { bonds: [], chess: getChess, priv: { ...priv, diyBanned: [] }, diyData: D }) }), null);
|
||||
// English: the msgid is in public/i18n/en.json
|
||||
const en = JSON.parse(readFileSync(path.join(ROOT, 'public/i18n/en.json'), 'utf8'));
|
||||
const id = '{names}的盟约本局全部禁用,不会出现在你的商店';
|
||||
assert.ok(en[id] && en[id].includes('{names}'), 'translated with its placeholder');
|
||||
addMessages('en', { [id]: en[id], 自选: en['自选'] });
|
||||
setLang('en');
|
||||
try {
|
||||
const t2 = textOf(DiyBannedLine({ model }));
|
||||
assert.ok(t2.includes('Custom') && t2.includes('not in your shop'), t2);
|
||||
} finally { setLang('zh'); }
|
||||
});
|
||||
@@ -193,17 +193,18 @@ test('the briefing, the strategy draft and the in-game 本局信息 tab all read
|
||||
const brief = read('public/js/screens/briefing.js');
|
||||
assert.match(brief, /import \{ MatchInfo, matchInfoModel \} from '\.\.\/ui\/matchInfo\.js';/);
|
||||
assert.match(brief, /<section class="brief__right">\s*<\$\{MatchInfo\} model=\$\{info\} \/>\s*<\/section>/);
|
||||
assert.match(brief, /const info = matchInfoModel\(pub, \{ bonds: gd\.list\('bonds'\), chess: gd\.chess, mode \}\);/);
|
||||
// (+ the viewer's 自选 pieces out of the shop: priv / diyData, 0.2.0 WE2)
|
||||
assert.match(brief, /const info = matchInfoModel\(pub, \{ bonds: gd\.list\('bonds'\), chess: gd\.chess, mode, priv, diyData: \{ chess: data\.get\('chess'\), backups: data\.get\('backups'\) \} \}\);/);
|
||||
assert.doesNotMatch(brief, /brief-legend|brief-banned|function BondRow|bannedPerBond|disabledBondSets/, 'no own copy of the blocks');
|
||||
const draft = read('public/js/screens/bandDraft.js');
|
||||
assert.match(draft, /import \{ MatchInfoDialog, matchInfoModel \} from '\.\.\/ui\/matchInfo\.js';/);
|
||||
assert.match(draft, /const info = infoOpen \? matchInfoModel\(pub, \{ bonds: gd\.list\('bonds'\), chess: gd\.chess, mode \}\) : null;/);
|
||||
assert.match(draft, /const info = infoOpen \? matchInfoModel\(pub, \{ bonds: gd\.list\('bonds'\), chess: gd\.chess, mode, priv, diyData: \{ chess: data\.get\('chess'\), backups: data\.get\('backups'\) \} \}\) : null;/);
|
||||
assert.match(draft, /data-testid="match-info-open"[\s\S]*?onClick=\$\{\(\) => setInfoOpen\(true\)\}>查看禁用盟约与干员</);
|
||||
assert.match(draft, /<\$\{MatchInfoDialog\} open=\$\{infoOpen\} onClose=\$\{\(\) => setInfoOpen\(false\)\} model=\$\{info\}/);
|
||||
// a turn change or my pick closes it; the draft's end unmounts the screen
|
||||
assert.match(draft, /const turnKey = `\$\{draft\.turnPid \|\| ''\}\|\$\{myPick \|\| ''\}`;\n\s*useEffect\(\(\) => \{ setInfoOpen\(false\); \}, \[turnKey\]\);/);
|
||||
const drawer = read('public/js/ui/enemyDrawer.js');
|
||||
assert.match(drawer, /import \{ matchInfoModel \} from '\.\/matchInfo\.js';/);
|
||||
assert.match(drawer, /import \{ matchInfoModel, DiyBannedLine \} from '\.\/matchInfo\.js';/);
|
||||
assert.match(drawer, /matchInfoModel\(pub, \{\s*bonds: data\.list\('bonds'\), chess: \(id\) => data\.lookup\('chess', id\), mode: data\.get\('config'\)\?\.modes\?\.\[pub\?\.modeId\],/);
|
||||
assert.doesNotMatch(drawer, /bannedPerBond|disabledBondSets/, 'the drawer derives nothing on its own');
|
||||
});
|
||||
Reference in new issue
Block a user