diff --git a/frontend/index.html b/frontend/index.html index 6f9c478..bd31c2a 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -956,7 +956,7 @@

Profile from card

- +
Ignore contents of files: @@ -7376,6 +7376,7 @@ function profilerFromCard() { document.getElementById('profiler-scan-btn').disabled = false; document.getElementById('profiler-scan-btn').textContent = t('Scan'); document.getElementById('profiler-scan-modal').classList.remove('hidden'); + document.getElementById('profiler-scan-name').focus(); } function profilerScanCancel() { @@ -7394,6 +7395,14 @@ function snapshotNew() { document.getElementById('profiler-scan-btn').disabled = false; document.getElementById('profiler-scan-btn').textContent = t('Scan'); document.getElementById('profiler-scan-modal').classList.remove('hidden'); + nameEl.focus(); +} + +function profilerScanNameKeydown(e) { + if (e.key !== 'Enter') return; + if (document.getElementById('profiler-scan-btn').disabled) return; + e.preventDefault(); + profilerScanStart(); } async function profilerScanStart() { diff --git a/frontend/sw.js b/frontend/sw.js index cf808d1..95220b3 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'otaman-v98'; +const CACHE = 'otaman-v99'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/html.test.js b/frontend/tests/html.test.js index ec908f6..70a2143 100644 --- a/frontend/tests/html.test.js +++ b/frontend/tests/html.test.js @@ -33,3 +33,7 @@ test('phone simulator has Phone / TR Config pills', () => { assert.ok(html.includes('id="phone-sub-phone"')); assert.ok(html.includes('id="phone-sub-tr"')); }); + +test('scan name input starts scanning on Enter', () => { + assert.match(html, /id="profiler-scan-name"[^>]*onkeydown="profilerScanNameKeydown\(event\)"/); +}); diff --git a/frontend/tests/profiler.test.js b/frontend/tests/profiler.test.js index cde6bbc..3857ccb 100644 --- a/frontend/tests/profiler.test.js +++ b/frontend/tests/profiler.test.js @@ -21,7 +21,7 @@ function extractFunc(src, name, asyncFn) { return (asyncFn ? 'async ' : '') + src.slice(m.index, i + 1); } -const FNS = ['profilerNormHex', 'profilerNormHexStrict', 'profilerMatch', 'profilerMatchMin', 'profilerMaskPrefix4', 'profilerFileFields', 'profilerContentKindForFileType', 'profilerEmptyRecordContent', 'profilerValidateProfile', 'profilerCustomNameForPath', 'profilerUpdateRulePath', 'profilerResultAspects', 'profilerAspectSummary', 'profilerNumRanges', 'esc', 'escHtml', 'profilerRawDataCheck', 'profilerRenderReport', 'parseBerLen', 'parseTlvList', 'fcpInt', 'fcpParseTlvs', 'fcpFileDescriptor', 'fcpLifeCycle', 'fcpSfi', 'fcpDo', 'fcpDecode', 'fcpDiffHtml', 'profilerFciPreviewItems', 'profilerUpdateFciPreview', 'profilerUpdateRule', 'profilerFciInput', 'profilerScanToggleAll', 'profilerScanIgnoreAllState', 'swapNibbles', 'decIccid', 'profilerSnapshotIccid', 'profilerValidateSnapshot', 'profilerListSwitch', 'profilerScanRefreshOptions', 'profilerLiveSource', 'profilerSnapshotSource', 'profilerVisibleResults', 'profilerMaskFidForFile', 'profilerRulesFromSnapshot', 'profilerExtraFileResults']; +const FNS = ['profilerNormHex', 'profilerNormHexStrict', 'profilerMatch', 'profilerMatchMin', 'profilerMaskPrefix4', 'profilerFileFields', 'profilerContentKindForFileType', 'profilerEmptyRecordContent', 'profilerValidateProfile', 'profilerCustomNameForPath', 'profilerUpdateRulePath', 'profilerResultAspects', 'profilerAspectSummary', 'profilerNumRanges', 'esc', 'escHtml', 'profilerRawDataCheck', 'profilerRenderReport', 'parseBerLen', 'parseTlvList', 'fcpInt', 'fcpParseTlvs', 'fcpFileDescriptor', 'fcpLifeCycle', 'fcpSfi', 'fcpDo', 'fcpDecode', 'fcpDiffHtml', 'profilerFciPreviewItems', 'profilerUpdateFciPreview', 'profilerUpdateRule', 'profilerFciInput', 'profilerScanToggleAll', 'profilerScanIgnoreAllState', 'swapNibbles', 'decIccid', 'profilerSnapshotIccid', 'profilerValidateSnapshot', 'profilerListSwitch', 'profilerScanRefreshOptions', 'profilerLiveSource', 'profilerSnapshotSource', 'profilerVisibleResults', 'profilerMaskFidForFile', 'profilerRulesFromSnapshot', 'profilerExtraFileResults', 'profilerScanNameKeydown']; let code = ''; for (const f of FNS) code += extractFunc(html, f) + '\n'; code += extractFunc(html, 'profilerBuildFileRule', true) + '\n'; @@ -1112,3 +1112,21 @@ test('profilerExtraFileResults reports files missing from the master', () => { assert.strictEqual(extras[0].status, 'fail'); assert.deepStrictEqual(extras[0].checks, [{ label: 'extra file', expected: 'absent', actual: 'present', ok: false }]); }); + +test('profilerScanNameKeydown starts the scan on Enter only', () => { + const btn = { disabled: false }; + global.document = { getElementById: () => btn }; + let started = 0; + global.profilerScanStart = () => { started++; }; + let prevented = 0; + profilerScanNameKeydown({ key: 'Enter', preventDefault: () => prevented++ }); + profilerScanNameKeydown({ key: 'a', preventDefault: () => prevented++ }); + assert.strictEqual(started, 1); + assert.strictEqual(prevented, 1); + btn.disabled = true; + profilerScanNameKeydown({ key: 'Enter', preventDefault: () => prevented++ }); + assert.strictEqual(started, 1); + assert.strictEqual(prevented, 1); + delete global.document; + delete global.profilerScanStart; +});