From 2e86692c3cc919bc9d93ddb5fa7eee1a12576f4d Mon Sep 17 00:00:00 2001 From: Brian Krabach Date: Mon, 30 Mar 2026 00:35:21 -0700 Subject: [PATCH] fix: add null guard to _updateNotificationUI and .catch() to requestPermission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _updateNotificationUI: add guard 'if (!statusEl || !reqBtn) return;' so future call sites without explicit null checks cannot throw TypeError - Notification.requestPermission(): add .catch(console.error) for defensive error handling — promise always resolves in practice but unhandled rejections would be silently swallowed - Tests: add test_update_notification_ui_has_null_guard and test_bind_static_event_listeners_permission_btn_has_catch to enforce both 435 tests pass (2 new) Co-authored-by: Amplifier --- muxplex/frontend/app.js | 3 +++ muxplex/tests/test_frontend_js.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index e5bf2c6..520eb79 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -1026,6 +1026,7 @@ function onDisplaySettingChange() { * @param {string} permission - Notification.permission value, or 'unsupported'. */ function _updateNotificationUI(statusEl, reqBtn, permission) { + if (!statusEl || !reqBtn) return; if (permission === 'granted') { statusEl.textContent = 'Granted'; reqBtn.disabled = true; @@ -1385,6 +1386,8 @@ function bindStaticEventListeners() { if (statusEl && reqBtn) { _updateNotificationUI(statusEl, reqBtn, permission); } + }).catch(function(err) { + console.error('Notification.requestPermission() failed:', err); }); }); } diff --git a/muxplex/tests/test_frontend_js.py b/muxplex/tests/test_frontend_js.py index b14a9a7..ff47100 100644 --- a/muxplex/tests/test_frontend_js.py +++ b/muxplex/tests/test_frontend_js.py @@ -1404,3 +1404,31 @@ def test_bind_static_event_listeners_permission_btn_calls_request_permission() - assert "requestPermission" in body, ( "bindStaticEventListeners permission button must call Notification.requestPermission()" ) + + +def test_bind_static_event_listeners_permission_btn_has_catch() -> None: + """Notification.requestPermission() in permission button handler must have a .catch() handler.""" + match = re.search( + r"function bindStaticEventListeners\s*\(\s*\)\s*\{(.*?)\n\}", + _JS, + re.DOTALL, + ) + assert match, "bindStaticEventListeners function not found" + body = match.group(1) + assert ".catch(" in body, ( + "Notification.requestPermission() must have a .catch() handler for defensive error handling" + ) + + +def test_update_notification_ui_has_null_guard() -> None: + """_updateNotificationUI must guard against null inputs.""" + match = re.search( + r"function _updateNotificationUI\s*\(.*?\)\s*\{(.*?)(?=\n\})", + _JS, + re.DOTALL, + ) + assert match, "_updateNotificationUI function not found" + body = match.group(1) + assert "null" in body or "non-null" in body or "!statusEl" in body or "!reqBtn" in body, ( + "_updateNotificationUI must include a null guard (null check) or JSDoc non-null annotation" + )