diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index 7341654..89aa9be 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -1851,7 +1851,7 @@ function renderSheetList() { (s.bell.seen_at === null || s.bell.last_fired_at > s.bell.seen_at); var isActive = s.name === _viewingSession; var escapedName = escapeHtml(s.name || ''); - var remoteIdAttr = s.remoteId ? ' data-remote-id="' + escapeHtml(s.remoteId) + '"' : ''; + var remoteIdAttr = s.remoteId != null ? ' data-remote-id="' + escapeHtml(s.remoteId) + '"' : ''; return '
  • ' + '' + escapedName + '' + diff --git a/muxplex/frontend/tests/test_app.mjs b/muxplex/frontend/tests/test_app.mjs index c44c788..6a3e6ba 100644 --- a/muxplex/frontend/tests/test_app.mjs +++ b/muxplex/frontend/tests/test_app.mjs @@ -1604,6 +1604,20 @@ test('renderSheetList escapes HTML special chars in sheet-item__name span', () = globalThis.document.getElementById = origGetById; }); +// --- Fix 3: renderSheetList uses null check for remoteId (not falsy) --- + +test('renderSheetList uses null check for remoteId (not falsy)', () => { + const source = fs.readFileSync(new URL('../app.js', import.meta.url), 'utf8'); + const fnStart = source.indexOf('function renderSheetList'); + const fnEnd = source.indexOf('\n}\n', fnStart + 100); + const fnBody = source.substring(fnStart, fnEnd); + // Must use != null check, not truthy check + assert.ok(fnBody.includes('remoteId != null') || fnBody.includes('remoteId !== null'), + 'renderSheetList must use null check for remoteId (0 is valid)'); + assert.ok(!fnBody.match(/s\.remoteId\s*\?[^=]/), + 'renderSheetList must NOT use truthy check for remoteId (0 is falsy)'); +}); + // --- Fix 2: openBottomSheet/closeBottomSheet use static backdrop binding --- test('openBottomSheet does not dynamically add click listener to sheet-backdrop', () => {