From 408454453026299a6d4d33ff625942f5089d61c7 Mon Sep 17 00:00:00 2001 From: Brian Krabach Date: Mon, 30 Mar 2026 23:41:50 -0700 Subject: [PATCH] refactor(task-9): extract badgeHtml const and tighten device badge tests - Extract inline ternary for device badge into `const badgeHtml` variable above the return block, consistent with how `bellHtml` is handled - Tighten data-session-key/data-source-url test assertions to check exact attribute values rather than just attribute presence - Add XSS test: verifies deviceName containing HTML is escaped in the badge All 159 tests pass. --- muxplex/frontend/app.js | 7 ++++++- muxplex/frontend/tests/test_app.mjs | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index 35f750a..5b7fc2b 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -463,6 +463,11 @@ function buildTileHTML(session, index, mobile) { bellHtml = `${countStr}`; } + // Device badge (shown when multiple sources configured and session has a device name) + const badgeHtml = _sources.length > 1 && session.deviceName + ? `${escapeHtml(session.deviceName)}` + : ''; + // Last 20 lines of snapshot const snapshot = session.snapshot || ''; const lastLines = snapshot.split('\n').slice(-20).join('\n'); @@ -470,7 +475,7 @@ function buildTileHTML(session, index, mobile) { return ( `
` + `
` + - `${escapeHtml(name)}${_sources.length > 1 && session.deviceName ? '' + escapeHtml(session.deviceName) + '' : ''}` + + `${escapeHtml(name)}${badgeHtml}` + `${bellHtml}${escapeHtml(timeStr)}` + `
` + `
${ansiToHtml(lastLines)}
` + diff --git a/muxplex/frontend/tests/test_app.mjs b/muxplex/frontend/tests/test_app.mjs index be83e7a..c29ad4c 100644 --- a/muxplex/frontend/tests/test_app.mjs +++ b/muxplex/frontend/tests/test_app.mjs @@ -2371,8 +2371,20 @@ test('buildTileHTML includes data-session-key and data-source-url attributes on snapshot: '', }; const html = app.buildTileHTML(session, 0, false); - assert.ok(html.includes('data-session-key='), 'article should have data-session-key attribute'); - assert.ok(html.includes('data-source-url='), 'article should have data-source-url attribute'); + assert.ok(html.includes('data-session-key="https://remote.example.com::work"'), 'article should have data-session-key with correct value'); + assert.ok(html.includes('data-source-url="https://remote.example.com"'), 'article should have data-source-url with correct value'); +}); + +test('buildTileHTML escapes HTML in deviceName within device-badge', () => { + app._setSources([ + { url: '', name: 'This device', type: 'local', status: 'authenticated', backoffMs: 2000 }, + { url: 'https://remote.example.com', name: 'Remote', type: 'remote', status: 'authenticated', backoffMs: 2000 }, + ]); + const session = { name: 'work', deviceName: '', sourceUrl: '', sessionKey: '::work', snapshot: '' }; + const html = app.buildTileHTML(session, 0, false); + assert.ok(!html.includes('