ReviewOS

also looking at this

craft-native/craft

feat(ios): tell the page about a notification that arrives while the app is open

#259
Merged glennmichael123 wants to merge feat/ios-notification-received into main
11 files +410 -58
packages/ios/src/page-script.test.tsmodified+44-0
Changes to packages/ios/src/page-script.test.ts
@@ -94,6 +94,8 @@ function loadPage(beforeInject?: (page: Record<string, any>) => void, seed = SEE
9494 // What CraftEventManager.handleNotificationResponse evaluates.
9595 tap: (detail: unknown) =>
9696 page.dispatchEvent(new CustomEvent('craftNotificationResponse', { detail })),
97 receive: (detail: unknown) =>
98 page.dispatchEvent(new CustomEvent('craftNotificationReceived', { detail })),
9799 }
98100}
99101
@@ -253,6 +255,48 @@ describe('the injected iOS page script', () => {
253255 expect(seen).toEqual([])
254256 })
255257
258 // #256: a notification that arrives while the page is open reaches it,
259 // live, on the notifications object the page ends up with.
260 it('hands a notification that arrived while the page was open to onReceive', () => {
261 const page = loadPage()
262 expect(typeof page.craft.notifications.onReceive).toBe('function')
263
264 const seen: unknown[] = []
265 const unsubscribe = page.craft.notifications.onReceive((detail: unknown) => seen.push(detail))
266 page.receive({ screen: 'recap' })
267 expect(seen).toEqual([{ screen: 'recap' }])
268
269 unsubscribe()
270 page.receive({ screen: 'plant-id' })
271 expect(seen).toEqual([{ screen: 'recap' }])
272 })
273
274 it('keeps arrivals and taps apart', async () => {
275 const page = loadPage()
276 const taps: unknown[] = []
277 const arrivals: unknown[] = []
278 page.craft.notifications.onTap((detail: unknown) => taps.push(detail))
279 page.craft.notifications.onReceive((detail: unknown) => arrivals.push(detail))
280 await tick()
281
282 page.receive({ screen: 'recap' })
283 page.tap({ screen: 'plant-id' })
284 expect(arrivals).toEqual([{ screen: 'recap' }])
285 expect(taps).toEqual([{ screen: 'plant-id' }])
286 })
287
288 // Held taps are for a launch the page was not there for. An arrival is
289 // news only to a page that is running, so nothing is held for later.
290 it('does not hold an arrival for a page that subscribes afterwards', async () => {
291 const page = loadPage()
292 page.receive({ screen: 'recap' })
293
294 const seen: unknown[] = []
295 page.craft.notifications.onReceive((detail: unknown) => seen.push(detail))
296 await tick()
297 expect(seen).toEqual([])
298 })
299
256300 // #198 and #215. The Android page script runs the same block; its own test
257301 // covers the rest of the contract.
258302 const tick = () => new Promise(resolve => setTimeout(resolve, 5))