ui: gate Read decoded on client-side decoder availability (v2.7.10)
Files without a client-side decoder used to fall back to a raw view when
the Decoded pill was pressed. The decoder is resolved by name/FID
(efFindDecoder) before any read, so the pill can be disabled instead.
- pysimFsHasDecoder() mirrors the decoded view's resolution (tree node
name, FID fallback).
- pysimApplyAvailability() honours a new data-needs-decoder marker:
disabled with the existing 'No decoder for this file' tooltip; the
card hint still wins when no card is equipped.
- pysimFsClickFile() re-runs the availability pass after selecting a
file; pysimFsSetMode('dec') ignores the call without a decoder.
- tests: indicator (enable/disable/tooltip precedence), fs_edit
(decoded guard, name/FID resolution); help EN/RU.
This commit is contained in:
@@ -49,6 +49,7 @@ function fakeEl() {
|
||||
},
|
||||
setAttribute(k, v) { this.attrs[k] = v; },
|
||||
getAttribute(k) { return this.attrs[k]; },
|
||||
hasAttribute(k) { return k in this.attrs; },
|
||||
removeAttribute(k) { delete this.attrs[k]; },
|
||||
};
|
||||
}
|
||||
@@ -225,6 +226,32 @@ test('card-iccid controls need an equipped card with a readable ICCID', () => {
|
||||
assert.strictEqual(el.disabled, true);
|
||||
});
|
||||
|
||||
test('Read decoded needs a client-side decoder for the selected file', () => {
|
||||
const run = (hasDecoder, cardEquipped) => {
|
||||
const el = fakeEl();
|
||||
el.setAttribute('data-needs', 'card');
|
||||
el.setAttribute('data-needs-decoder', '');
|
||||
globalThis.document = { querySelectorAll: () => [el], getElementById: () => null };
|
||||
_pysimServerAvailable = true;
|
||||
_pysimCardEquipped = cardEquipped;
|
||||
globalThis.pysimFsHasDecoder = () => hasDecoder;
|
||||
pysimApplyAvailability();
|
||||
return el;
|
||||
};
|
||||
// decoder present, card equipped -> enabled, no tooltip
|
||||
let el = run(true, true);
|
||||
assert.strictEqual(el.disabled, false);
|
||||
assert.strictEqual(el.attrs.title, undefined);
|
||||
// no decoder -> disabled with its own hint
|
||||
el = run(false, true);
|
||||
assert.strictEqual(el.disabled, true);
|
||||
assert.strictEqual(el.attrs.title, 'No decoder for this file');
|
||||
// card missing and no decoder -> the card hint wins
|
||||
el = run(false, false);
|
||||
assert.strictEqual(el.disabled, true);
|
||||
assert.strictEqual(el.attrs.title, 'Insert and equip a card');
|
||||
});
|
||||
|
||||
test('indicator image stays within the 32px header row budget', () => {
|
||||
const m = /id="state-indicator-img"[^>]*style="width:(\d+)px;height:(\d+)px"/.exec(html);
|
||||
assert.ok(m, 'inline image size not found');
|
||||
|
||||
Reference in New Issue
Block a user