// The service-table rows' cross-link to the file-tree filter: a table row // that is backed by files gets a "To EF filter" button that narrows the tree // to exactly that service's files. 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); } function extractConst(src, name) { const m = new RegExp('const ' + name + ' = ').exec(src); if (!m) throw new Error('const ' + name + ' not found'); const begin = m.index + m[0].length; const opener = src[begin]; const closer = opener === '[' ? ']' : (opener === '{' ? '}' : null); if (!closer) throw new Error('unsupported const ' + name); let depth = 0, i = begin; for (; i < src.length; i++) { if (src[i] === opener) depth++; else if (src[i] === closer) { depth--; if (depth === 0) { i++; break; } } } return 'var ' + name + ' = ' + src.slice(begin, i) + ';\n'; } // module state the extracted functions close over let pysimFsFilter = new Set(['all']); let _servicesFeatureByNumber = null; // the tree filter's matching-path cache (pysimFsSetFilterToService drops it) let _fsFilterPaths = null; let _fsFilterPathsKey = null; const _store = {}; let _renders = 0; let _treeRenders = 0; globalThis.localStorage = { getItem: k => (Object.prototype.hasOwnProperty.call(_store, k) ? _store[k] : null), setItem: (k, v) => { _store[k] = String(v); }, removeItem: k => { delete _store[k]; }, }; globalThis.esc = s => String(s); globalThis.t = k => k; globalThis.pysimFsFilterRender = () => { _renders++; }; globalThis.pysimFsRenderTree = () => { _treeRenders++; }; let code = ''; for (const f of ['servicesFeatureByNumber', 'pysimFsFilterBtnHtml', 'pysimFsSetFilterToService', 'pysimFsFilterPathsInvalidate']) { code += extractFunc(html, f) + '\n'; } for (const c of ['SERVICES_CROSS_REF', 'SERVICES_FS_MAP']) code += extractConst(html, c); eval(code); test('servicesFeatureByNumber inverts the cross-reference per file table', () => { const map = servicesFeatureByNumber(); assert.strictEqual(map.ust[2], 'Fixed Dialling Numbers (FDN)'); assert.strictEqual(map.sst[2], 'Local Phone Book (ADN)'); assert.strictEqual(map.est[1], 'Fixed Dialling Numbers (FDN)'); assert.strictEqual(map.ist[1], 'P-CSCF address'); // the same number names a different feature in another table assert.strictEqual(map.ust[1], 'Local Phone Book (ADN)'); assert.strictEqual(map.sst[1], 'CHV1 disable function'); // a capability-only number maps to a feature too assert.strictEqual(map.ust[99], 'URI support by UICC'); // the map is built once assert.strictEqual(servicesFeatureByNumber(), map); }); test('pysimFsFilterBtnHtml links a file-backed service row only', () => { const out = pysimFsFilterBtnHtml('ust', 2); assert.match(out, /^