fix: the TAR probe view auto-selects the preset; the keyset selectors refresh (v3.8.0)
Two selector bugs in the new TAR-probe view and one stale-list bug in the RAM view, all from the lazy population of the view-specific preset selects: - cardsAutoSelectByIccid() set sp-card-sel and ram-card-sel only, so the TAR probe view never got the equipped card's preset (and tarExecute() then ran with preset_id: '', i.e. without persisting the counters it consumed); - tarRender()'s keep-fallback was -1 instead of the remembered _ramCardIdx, so the select stayed on "— Select card —" even when the auto-selection had remembered the preset; the TAR pill switch now also calls tarRender(); - the keyset selectors showed a stale "N — not defined in the preset": spKeysetSync() runs during the auto-selection, when ram/tar-card-sel have no options yet, so those lists were built with no preset; ramRender() now rebuilds them (spKeysetSync) once its preset is known - tarRender() already did. Tests: the auto-select covers tar-card-sel; a DOM-driven regression test (ramRender with a remembered preset and a two-keyset preset must show value="2" selected and no "not defined" entry); source guards for ramRender's sync, tarRender's keep and the TAR pill switch. sw cache simple-v339.
This commit is contained in:
+11
-3
@@ -1831,7 +1831,7 @@ function scp80SwitchSubtab(name) {
|
||||
document.getElementById('scp80-sub-ram').classList.toggle('hidden', name !== 'ram');
|
||||
document.getElementById('scp80-sub-tar').classList.toggle('hidden', name !== 'tar');
|
||||
if (name === 'ram') ramRender();
|
||||
if (name === 'tar') tarProbeRender();
|
||||
if (name === 'tar') { tarRender(); tarProbeRender(); }
|
||||
scp80HelpAnchor = { sp: 'secured-packet', ram: 'ram', tar: 'tar-probe' }[name] || 'secured-packet';
|
||||
setHelpAnchor(scp80HelpAnchor);
|
||||
}
|
||||
@@ -8402,6 +8402,10 @@ function ramRender() {
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
if (keep !== null && keep !== undefined && cards[keep]) sel.value = String(keep);
|
||||
// the keyset selector is built from this view's preset: rebuild it now that
|
||||
// the preset is known (the auto-selection runs before the select has its
|
||||
// options, which used to leave a stale "not defined in the preset" entry)
|
||||
spKeysetSync();
|
||||
ramOpChanged();
|
||||
ramExpandedDetailsInit();
|
||||
}
|
||||
@@ -10695,7 +10699,9 @@ function tarRender() {
|
||||
const sel = document.getElementById('tar-card-sel');
|
||||
if (!sel) return;
|
||||
const prev = parseInt(sel.value, 10);
|
||||
const keep = (!isNaN(prev) && cards[prev]) ? prev : -1;
|
||||
// keep the current/remembered selection across rebuilds (the auto-selection
|
||||
// sets _ramCardIdx before this select has its options)
|
||||
const keep = (!isNaN(prev) && cards[prev]) ? prev : _ramCardIdx;
|
||||
sel.innerHTML = '<option value="" data-l10n="— Select card —">— Select card —</option>';
|
||||
cards.forEach((c, i) => {
|
||||
const opt = document.createElement('option');
|
||||
@@ -10703,7 +10709,7 @@ function tarRender() {
|
||||
opt.textContent = c.name || ('Card ' + i);
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
if (keep >= 0) sel.value = String(keep);
|
||||
if (keep !== null && keep !== undefined && cards[keep]) sel.value = String(keep);
|
||||
spKeysetSync();
|
||||
}
|
||||
|
||||
@@ -11849,6 +11855,8 @@ function cardsAutoSelectByIccid(iccid) {
|
||||
if (sp) sp.value = String(idx);
|
||||
const ram = document.getElementById('ram-card-sel');
|
||||
if (ram) ram.value = String(idx);
|
||||
const tar = document.getElementById('tar-card-sel');
|
||||
if (tar) tar.value = String(idx);
|
||||
_ramCardIdx = idx;
|
||||
cardsApply(String(idx));
|
||||
return idx;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v338';
|
||||
const CACHE = 'simple-v339';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
@@ -34,7 +34,8 @@ const RAW_HEX = '980711090000640090F8';
|
||||
const DIGITS = '8970119000004600098';
|
||||
|
||||
function fakeDoc() {
|
||||
const els = { 'sp-card-sel': { value: '' }, 'ram-card-sel': { value: '' }, 'cards-iccid': { value: '' } };
|
||||
const els = { 'sp-card-sel': { value: '' }, 'ram-card-sel': { value: '' },
|
||||
'tar-card-sel': { value: '' }, 'cards-iccid': { value: '' } };
|
||||
globalThis.document = { getElementById: id => els[id] || null };
|
||||
return els;
|
||||
}
|
||||
@@ -78,6 +79,8 @@ test('cardsAutoSelectByIccid selects the preset in both SCP80 views', () => {
|
||||
assert.strictEqual(idx, 0);
|
||||
assert.strictEqual(els['sp-card-sel'].value, '0');
|
||||
assert.strictEqual(els['ram-card-sel'].value, '0');
|
||||
assert.strictEqual(els['tar-card-sel'].value, '0',
|
||||
'the TAR probe view gets the equipped card\'s preset too');
|
||||
assert.deepStrictEqual(applied, ['0']);
|
||||
assert.strictEqual(globalThis._ramCardIdx, 0);
|
||||
});
|
||||
@@ -162,5 +165,7 @@ test('the From card button and the duplicate refusal are wired into the form', (
|
||||
test('the card-state update wires the ICCID into the preset selection', () => {
|
||||
assert.ok(html.includes('cardsAutoSelectByIccid(status.iccid);'));
|
||||
assert.ok(html.includes('_cardsAutoIccid = null;'));
|
||||
assert.ok(html.includes("getElementById('tar-card-sel')"),
|
||||
'the auto-selection must cover the TAR probe view');
|
||||
assert.ok(html.includes("(data.iccid ? ' | ICCID: <b>' + esc(data.iccid) + '</b>' : '')"));
|
||||
});
|
||||
|
||||
@@ -23,7 +23,8 @@ function extractFunc(src, name) {
|
||||
|
||||
let code = '';
|
||||
for (const fn of ['spKeysetKvnOf', 'spKeysetList', 'spKeysetFor', 'spKeysetCheck',
|
||||
'spKeysetOptionsHtml', 'spCounterTracked', 'esc', 'escHtml']) {
|
||||
'spKeysetOptionsHtml', 'spCounterTracked', 'spPresetIdx', 'ramPresetIdx',
|
||||
'tarPresetIdx', 'spKeysetSync', 'ramRender', 'esc', 'escHtml']) {
|
||||
code += extractFunc(html, fn) + '\n';
|
||||
}
|
||||
code += 'function t(s){return s;}\n';
|
||||
@@ -131,3 +132,46 @@ test('spCounterTracked follows SPI1 b5b4 (TS 102 225 5.1.1)', () => {
|
||||
}
|
||||
assert.strictEqual(spCounterTracked('zz'), false);
|
||||
});
|
||||
|
||||
test('ramRender rebuilds the keyset selector from the remembered preset', () => {
|
||||
// regression: the auto-selection runs before the RAM select has options, so
|
||||
// its keyset list was built with no preset and stayed on "not defined"
|
||||
const els = {
|
||||
'ram-card-sel': { value: '', innerHTML: '', appendChild() {} },
|
||||
'ram-keyset-sel': { value: '', innerHTML: '' },
|
||||
'sp-keyset-sel': { value: '', innerHTML: '' },
|
||||
'tar-keyset-sel': { value: '', innerHTML: '' },
|
||||
'sp-kic-hex': { value: '25' },
|
||||
'sp-kid-hex': { value: '25' },
|
||||
};
|
||||
globalThis.document = {
|
||||
getElementById: id => els[id] || null,
|
||||
createElement: () => ({ value: '', textContent: '' }),
|
||||
};
|
||||
globalThis.cards = [{ name: 'EP', keysets: [
|
||||
{ kic: '15', kid: '15', kicKey: 'AA', kidKey: 'BB', cntr: '0000000001' },
|
||||
{ kic: '25', kid: '25', kicKey: 'CC', kidKey: 'DD', cntr: '0000000184' }] }];
|
||||
globalThis._ramCardIdx = 0;
|
||||
globalThis.ramOpChanged = () => {};
|
||||
globalThis.ramExpandedDetailsInit = () => {};
|
||||
ramRender();
|
||||
assert.strictEqual(els['ram-card-sel'].value, '0',
|
||||
'the preset select keeps the remembered card');
|
||||
assert.match(els['ram-keyset-sel'].innerHTML, /value="2" selected/);
|
||||
assert.ok(!els['ram-keyset-sel'].innerHTML.includes('not defined'),
|
||||
'the keyset selector must not show a stale "not defined" entry');
|
||||
});
|
||||
|
||||
test('the RAM and TAR views rebuild their keyset lists when their preset is known', () => {
|
||||
// ramRender() syncs the keyset selectors once the preset is set ...
|
||||
const ram = html.slice(html.indexOf('function ramRender()'),
|
||||
html.indexOf('function ramRender()') + 1400);
|
||||
assert.ok(ram.includes('spKeysetSync();'), 'ramRender must rebuild the keyset lists');
|
||||
// ... tarRender() already does, and keeps the remembered selection
|
||||
const tar = html.slice(html.indexOf('function tarRender()'),
|
||||
html.indexOf('function tarRender()') + 1200);
|
||||
assert.ok(tar.includes('spKeysetSync();'));
|
||||
assert.ok(tar.includes(': _ramCardIdx;'), 'tarRender keeps the remembered preset');
|
||||
// opening the TAR pill populates both its selectors
|
||||
assert.ok(html.includes("if (name === 'tar') { tarRender(); tarProbeRender(); }"));
|
||||
});
|
||||
|
||||
@@ -28,6 +28,7 @@ const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamB
|
||||
'ramExpandedReport', 'ramExpandedTags', 'ramExpandedGroups', 'ramExpandedElfForm', 'ramElfVersionHint', 'ramChainGetResponse', 'ramDeriveElfVersions', 'ramElfAppletCandidate',
|
||||
'spCntrLow', 'ramCntrLowHtml', 'ramCntrLowPresetIdx', 'ramShowCntrLow',
|
||||
'spKeysetKvnOf', 'spKeysetList', 'spKeysetFor', 'spKeysetCheck',
|
||||
'spKeysetOptionsHtml', 'spPresetIdx', 'tarPresetIdx',
|
||||
'cardsKeysetsFromForm', 'spKeysetSync', 'spKeysetApply', 'spKeysetChanged',
|
||||
'ramKeysetChanged', 'ramPresetIdx', 'spKeysetGuard', 'ramKeysetGuard',
|
||||
'ramCardIdxAfterRemove', 'ramClearResults', 'ramHideProgress', 'ramOpChanged', 'ramRender', 'ramApplyCard', 'ramExecute', 'decodePrivileges', 'ramActionBtn', 'ramCapToolkitMode', 'ramOpProgressText',
|
||||
|
||||
Reference in New Issue
Block a user