ui: hide, don't clear, children of non-selectable DFs

- 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.
This commit is contained in:
2026-09-12 21:23:31 +03:00
parent 92271d6726
commit 85a66af7a5
5 changed files with 50 additions and 23 deletions
+20 -1
View File
@@ -104,7 +104,7 @@ test('an absent directory is marked and its subtree is never fetched', async ()
await pysimFsProbeAll();
assert.strictEqual(pysimFsTreeRoot.children[0].exists, false);
assert.deepStrictEqual(selectNames(), ['EF.ROOT']);
assert.strictEqual(calls.filter(c => c.path === '/api/tree' && c.body.name === 'DF.B').length, 2);
assert.strictEqual(calls.filter(c => c.path === '/api/tree' && c.body.name === 'DF.B').length, 1);
const status = els['pysim-fs-probe-status'].textContent;
assert.match(status, /2\/2 files/);
assert.match(status, /0 present/);
@@ -122,3 +122,22 @@ test('stop halts the walk and still reports a summary', async () => {
assert.ok(status.startsWith('Stopped —'), status);
assert.strictEqual(els['pysim-fs-probe-btn'].textContent, 'Probe all files');
});
test('children of an absent directory are neither fetched nor selected', async () => {
const stale = Object.assign(df('DF.C', '5f03'), {
exists: false,
children: [{ name: 'EF.STALE', fid: '6f0e', isDir: false, exists: true, children: null }],
});
root([stale, ef('EF.ROOT', '2f01')]);
setup([
{ path: '/api/select', name: 'EF.ROOT', reply: { exists: true } },
]);
await pysimFsProbeAll();
assert.deepStrictEqual(selectNames(), ['EF.ROOT']);
assert.strictEqual(stale.exists, false);
assert.strictEqual(calls.filter(c => c.path === '/api/tree').length, 0);
const status = els['pysim-fs-probe-status'].textContent;
assert.match(status, /2\/2 files/);
assert.match(status, /1 present/);
assert.match(status, /1 absent/);
});