aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-09 14:01:08 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-09 14:02:19 +0200
commitf2517faca8d35772fb03272ee7f8056421ce2198 (patch)
treee345e2291a99e29acfafc755251cd7925ad96ca9 /packages/meshbay-hub/tests
parent4ae61dc4e1dcca6ae24131fcd9acc55124e3c0af (diff)
downloadmeshbay-f2517faca8d35772fb03272ee7f8056421ce2198.tar.gz
fix(hub): an open application looks for new notifications when you come back
The page asked for the notification list at sign-in and at a token renewal, and at no other time. A notification created after the application started, such as a chat line the hub wrote 20 ms after the message, stayed unseen until the next launch. The hub has no channel to the page and is not polled on a timer, so the list is asked for again on a gesture: the application returning to the foreground (an Android phone included) and the home page, where the list is shown. Two requests less than 30 s apart count as one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests')
-rw-r--r--packages/meshbay-hub/tests/test_notification_refresh.py48
1 files changed, 48 insertions, 0 deletions
diff --git a/packages/meshbay-hub/tests/test_notification_refresh.py b/packages/meshbay-hub/tests/test_notification_refresh.py
new file mode 100644
index 0000000..9e41f0c
--- /dev/null
+++ b/packages/meshbay-hub/tests/test_notification_refresh.py
@@ -0,0 +1,48 @@
+"""
+An open application asks for the notification list again when somebody comes back.
+
+Reported live on 2026-10-09: a member posted in a group, the hub wrote the
+owner's notification 20 ms later, and the owner, whose application was open,
+never saw it. Nothing was broken on the hub or the node. The page asked for the
+list at sign-in (and at a token renewal, every few hours) and at no other time,
+so a notification created after the application started waited for the next
+launch.
+
+The hub has no channel to the page and is deliberately not polled on a timer,
+so the list is asked for again on a gesture: the application returning to the
+foreground, or the home page, where the list is shown. Two in a row are one
+question. These read the source; there is no browser for the SPA's state here.
+"""
+
+import re
+from pathlib import Path
+
+APP = (Path(__file__).resolve().parents[1] / "src" / "meshbay_hub" / "static"
+ / "app.js").read_text()
+
+
+def _block(start: str) -> str:
+ i = APP.index(start)
+ return APP[i:APP.index("\n }, [", i)]
+
+
+def test_coming_back_to_the_application_asks_again():
+ listeners = [m.start() for m in re.finditer(r"addEventListener\('visibilitychange'", APP)]
+ bodies = [APP[APP.rfind("useEffect(", 0, i):i] for i in listeners]
+ assert any("refreshNotifications()" in b and "'visible'" in b for b in bodies), \
+ "no visibilitychange listener asks for the notification list"
+
+
+def test_the_home_page_asks_again():
+ assert re.search(r"if \(user && route === '/'\) refreshNotifications\(\);", APP)
+
+
+def test_two_askings_in_a_row_are_one_and_no_timer_asks():
+ refresh = _block("const refreshNotifications = useCallback(")
+ assert "NOTIF_REFRESH_MS" in refresh and "fetchNotifications()" in refresh
+ # The stamp is taken where the request leaves, so the sign-in fetch counts
+ # and the home page right after it does not ask a second time.
+ fetch = _block("const fetchNotifications = useCallback(")
+ assert "notifAskedAtRef.current = Date.now()" in fetch
+ for timer in re.finditer(r"setInterval\(([^,]+),", APP):
+ assert "otif" not in timer.group(1), "the notification list is polled on a timer"