85a66af7a5
- pysimFsLoadChildren failure now only marks exists=false and re-renders; loaded children stay in the node and are hidden by the renderer (red cross, no toggle, no (empty)), so a failed DF is re-attempted on the next probe/refresh instead of being short-circuited - dropped the parent_sel-less /api/tree retry: error payloads now carry exists:false, so it doubled requests for every absent DF and re-selected the same FID without its parent (pySim probe_file fallback) - probe walks strictly on exists===true and never collects files under a non-existing DF; no longer clears children on a failed EF select - tests updated: single request per failed load, children untouched, 200 exists:false marks absent without retry, render hides stale children, probe never fetches/selects them; SW cache v116 -> v117.
68 lines
2.6 KiB
JavaScript
68 lines
2.6 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const html = fs.readFileSync(path.join(__dirname, '..', 'index.html'), 'utf8');
|
|
|
|
function extractFunc(src, name) {
|
|
const re = new RegExp('(?:async\\s+)?function\\s+' + name + '\\s*\\([^)]*\\)\\s*\\{');
|
|
const m = re.exec(src);
|
|
if (!m) throw new Error('function ' + name + ' not found');
|
|
let i = m.index + m[0].length - 1;
|
|
let depth = 0;
|
|
for (; i < src.length; i++) {
|
|
if (src[i] === '{') depth++;
|
|
else if (src[i] === '}') {
|
|
depth--;
|
|
if (depth === 0) break;
|
|
}
|
|
}
|
|
return src.slice(m.index, i + 1);
|
|
}
|
|
|
|
let code = 'var pysimFsSort = "fid";\n';
|
|
code += extractFunc(html, 'pysimFsSortChildren') + '\n';
|
|
code += extractFunc(html, 'pysimFsRenderNode') + '\n';
|
|
code += 'globalThis.esc = s => s;\nglobalThis.t = s => s;\n';
|
|
eval(code);
|
|
|
|
const ef = (name, fid) => ({ name, fid, isDir: false, exists: true, children: null, expanded: false });
|
|
const df = (name, fid, extra) => Object.assign({ name, fid, isDir: true, exists: true, children: null, expanded: false }, extra || {});
|
|
|
|
test('absent directory renders a cross and no expand toggle', () => {
|
|
const node = df('DF.WLAN', '5f40', { exists: false, children: [] });
|
|
const out = pysimFsRenderNode(node, 0);
|
|
assert.ok(out.includes('✗'), out);
|
|
assert.ok(!out.includes('pysimFsToggleDir'), out);
|
|
assert.ok(!out.includes('▶'), out);
|
|
});
|
|
|
|
test('expanded empty directory shows the (empty) placeholder', () => {
|
|
const node = df('DF.EMPTY', '5f00', { children: [], expanded: true });
|
|
const out = pysimFsRenderNode(node, 0);
|
|
assert.ok(out.includes('(empty)'), out);
|
|
});
|
|
|
|
test('expanded directory with children renders no placeholder', () => {
|
|
const node = df('DF.GSM', '7f20', { children: [ef('EF.IMSI', '6f07')], expanded: true });
|
|
const out = pysimFsRenderNode(node, 0);
|
|
assert.ok(out.includes('EF.IMSI'), out);
|
|
assert.ok(!out.includes('(empty)'), out);
|
|
});
|
|
|
|
test('collapsed directory hides its children', () => {
|
|
const node = df('DF.GSM', '7f20', { children: [ef('EF.IMSI', '6f07')], expanded: false });
|
|
const out = pysimFsRenderNode(node, 0);
|
|
assert.ok(!out.includes('EF.IMSI'), out);
|
|
});
|
|
|
|
test('non-existing directory hides previously loaded children', () => {
|
|
const node = df('DF.WLAN', '5f40', { exists: false, expanded: true, children: [ef('EF.UPLMNWLAN', '4f42')] });
|
|
const out = pysimFsRenderNode(node, 0);
|
|
assert.ok(out.includes('✗'), out);
|
|
assert.ok(!out.includes('EF.UPLMNWLAN'), out);
|
|
assert.ok(!out.includes('(empty)'), out);
|
|
assert.ok(!out.includes('pysimFsToggleDir'), out);
|
|
});
|