aboutsummaryrefslogtreecommitdiffstats
path: root/tools/sw-push-quota.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/sw-push-quota.test.js')
-rw-r--r--tools/sw-push-quota.test.js45
1 files changed, 40 insertions, 5 deletions
diff --git a/tools/sw-push-quota.test.js b/tools/sw-push-quota.test.js
index e7d00f2..798b913 100644
--- a/tools/sw-push-quota.test.js
+++ b/tools/sw-push-quota.test.js
@@ -4,8 +4,9 @@
import { test, expect, mock } from 'bun:test';
let respond = async () => true;
-mock.module('../src/nwc-respond.js', () => ({ respondFromBg: (...a) => respond(...a), tendRenewals: async () => {} }));
-mock.module('../src/nwc-lock.js', () => ({ withRequestLock: async (_id, fn) => fn() }));
+mock.module('../src/nwc-respond.js', () => ({ respondFromBg: (...a) => respond(...a), tendRenewals: async () => {}, tendLnPays: async () => [] }));
+mock.module('../src/nwc-lock.js', () => ({ withRequestLock: async (_id, fn) => fn(), withWorkLock: async (fn) => fn() }));
+mock.module('../src/nwc-bg.js', () => ({ appendBgLog: async () => {}, takeLease: async () => ({ waited: 0, release: async () => {} }) }));
mock.module('../src/bg-autowithdraw.js', () => ({ bgAutoWithdraw: async () => {} }));
mock.module('../src/dm-inbox.js', () => ({
allInboxes: async () => [{ muted: ['m'.repeat(64)] }],
@@ -50,6 +51,13 @@ test('apple: every quiet path shows the stand-in', async () => {
expect(closed.length).toBe(0);
});
+test('apple: a send finished from an earlier wake shows its own line and drops the stand-in', async () => {
+ endpoint = 'https://web.push.apple.com/abc'; windows = [];
+ respond = async () => ({ notices: [{ title: 'Payment sent', body: '-21 sats via a connected app', tag: 'nwc-sent' }] });
+ expect(await push(nwc)).toEqual(['Coinos', 'Payment sent']);
+ expect(closed.length).toBe(1);
+});
+
test('apple: an app on screen gets the stand-in closed at once', async () => {
windows = [visible];
expect(await push({ type: 'notify', reason: 'payment', amountSat: 5 })).toEqual(['Coinos']);
@@ -60,7 +68,9 @@ test('apple: a suspended background app does not swallow the request', async ()
windows = [hidden];
let asked = 0;
respond = async () => { asked++; return { notify: { title: 'Payment sent', body: '' } }; };
- expect(await push(nwc)).toEqual(['Payment sent']);
+ // the stand-in goes up first and the outcome replaces it (91dbee4)
+ expect(await push(nwc)).toEqual(['Coinos', 'Payment sent']);
+ expect(closed.length).toBe(1);
expect(asked).toBe(1);
});
@@ -72,8 +82,33 @@ test('elsewhere: quiet stays quiet', async () => {
let asked = 0;
respond = async () => { asked++; return true; };
expect(await push(nwc)).toEqual([]);
- expect(asked).toBe(0); // the open (if hidden) window answers on Android
+ expect(asked).toBe(0); // on a computer the open (if hidden) window answers
windows = [];
respond = async () => false;
- expect(await push(nwc)).toEqual(['Payment request']);
+ expect(await push(nwc)).toEqual(['Spend request']);
+});
+
+// An Android phone freezes an app behind another one, minutes in: its relay
+// sockets are dead and the worker's nudge sits unread until it is opened, so
+// a zap sent from another app spun until then (wake to payment: 15 s at the
+// median on Android, 2026-11-10). On a phone only a window on screen is
+// handed the request; behind another app, the worker answers (and nudges the
+// window anyway — the request's lock decides if it is still awake).
+test('an Android phone: the app behind another one does not swallow the request', async () => {
+ endpoint = 'https://fcm.googleapis.com/fcm/send/abc';
+ self.navigator = { userAgent: 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Mobile Safari/537.36' };
+ try {
+ let asked = 0, nudged = 0;
+ respond = async () => { asked++; return true; };
+ windows = [{ visibilityState: 'hidden', postMessage: () => { nudged++; } }];
+ expect(await push(nwc)).toEqual([]);
+ expect(asked).toBe(1);
+ expect(nudged).toBe(1);
+ // on screen, it answers itself with everything it knows
+ asked = 0; nudged = 0;
+ windows = [{ visibilityState: 'visible', postMessage: () => { nudged++; } }];
+ expect(await push(nwc)).toEqual([]);
+ expect(asked).toBe(0);
+ expect(nudged).toBe(1);
+ } finally { delete self.navigator; }
});