diff --git a/frontend/index.html b/frontend/index.html index c29149e..b08d480 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7820,10 +7820,12 @@ async function profilerScanCard(ignoreFids, ignoreNames, fciMode, onProgress, ma const files = []; const seen = new Set(); - // dir: { name, fid, parentSel (to select this dir), pathPrefix (rule-path segs for its children) } + // dir: { name, fid, parentSel (legacy), parentPath (full path of this dir), + // pathPrefix (rule-path segs for its children) } async function walkDir(dir) { let body = { name: dir.name, fid: dir.fid }; - if (dir.parentPath && dir.parentPath.length) body.parent_path = dir.parentPath; + const parentPath = (dir.parentPath || []).slice(0, -1); + if (parentPath.length) body.parent_path = parentPath; if (dir.parentSel) body.parent_sel = dir.parentSel; let data; try { @@ -7835,12 +7837,13 @@ async function profilerScanCard(ignoreFids, ignoreNames, fciMode, onProgress, ma const parentSel = (dir.name === 'MF') ? 'MF' : (dir.name && dir.name.startsWith('ADF.')) ? dir.name : (dir.fid ? dir.fid : dir.name); + const childSeg = c.aid ? c.aid.toUpperCase() : (c.fid ? c.fid : c.name); if (c.isDir) { // ADF roots use the AID, not the generic ADF fid const childPrefix = c.aid ? [c.aid.toUpperCase()] : dir.pathPrefix.concat(c.fid ? c.fid.toUpperCase() : c.name); - const childParentPath = (dir.parentPath || []).concat(c.aid ? c.aid.toUpperCase() : (c.fid ? c.fid : c.name)); - await walkDir({ name: c.name, fid: c.fid, parentSel: parentSel, parentPath: childParentPath, pathPrefix: childPrefix }); + const childDirPath = dir.parentPath.concat(childSeg); + await walkDir({ name: c.name, fid: c.fid, parentSel: parentSel, parentPath: childDirPath, pathPrefix: childPrefix }); } else { const childPath = dir.pathPrefix.concat(c.fid ? c.fid.toUpperCase() : c.name).join('/'); if (seen.has(childPath)) continue; diff --git a/frontend/sw.js b/frontend/sw.js index 20efe1c..e4f8e0e 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'otaman-v132'; +const CACHE = 'otaman-v133'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/profiler.test.js b/frontend/tests/profiler.test.js index b4036e2..cd02da7 100644 --- a/frontend/tests/profiler.test.js +++ b/frontend/tests/profiler.test.js @@ -947,6 +947,32 @@ test('profilerScanCard snapshot mode builds snapshot entries with ICCID', async delete global.pysimCustomFiles; }); +test('profilerScanCard walks nested dirs with their parent path, not their own segment', async () => { + global.pysimCustomFiles = []; + const treeCalls = []; + global.pysimFetch = async (path, body) => { + if (path === '/api/tree') { + treeCalls.push(body); + if (body.name === 'MF') return { exists: true, name: 'MF', children: [ + { name: 'EF.DIR', fid: '2f00', isDir: false }, + { name: 'DF.GSM', fid: '7f20', isDir: true }, + ] }; + if (body.name === 'DF.GSM') return { exists: true, name: 'DF.GSM', children: [ + { name: 'EF.ADN', fid: '6f3a', isDir: false }, + ] }; + throw new Error('unexpected tree ' + body.name); + } + if (path === '/api/select') return { name: 'X', fid: '0000', file_type: 'transparent', file_size: 1, record_len: null, num_of_rec: null, exists: true }; + if (path === '/api/read') return { success: true, data: 'AA' }; + throw new Error('unexpected ' + path); + }; + const files = await profilerScanCard(new Set(), new Set(), 'type', undefined, new Set(), 'snapshot'); + // MF root has no parent; DF.GSM must be looked up under MF, not under itself + assert.deepStrictEqual(treeCalls.map(b => b.parent_path), [undefined, ['MF']]); + assert.deepStrictEqual(files.map(f => f.path).sort(), ['MF/2F00', 'MF/7F20/6F3A']); + delete global.pysimCustomFiles; +}); + test('profilerListSwitch toggles the profiles/snapshots tabs', () => { const mkBtn = tab => ({ dataset: { listTab: tab },