ReviewOS

also looking at this

craft-native/craft

test(ios): tap a real pushed notification that launches the app, and judge what the page gets

#257
Merged glennmichael123 wants to merge test/ios-e2e-notification-tap into main
5 files +308 -10
scripts/mobile-e2e/driver.htmlmodified+44-0
Changes to scripts/mobile-e2e/driver.html
@@ -15,6 +15,8 @@
1515 <h1 id="headline">Craft mobile E2E</h1>
1616 <ul id="results"></ul>
1717 <p id="deeplink"></p>
18 <p id="notification-permission"></p>
19 <p id="notification"></p>
1820 <script>
1921 // The page drives itself and reports through the bridge's own `log` action,
2022 // which is the one channel both runtimes already forward off-device: iOS
@@ -36,6 +38,13 @@
3638 var dispatchedLinks = []
3739 window.addEventListener('craftDeepLink', function (event) { dispatchedLinks.push(event.detail || {}) })
3840
41 // Every notification tap the native side dispatches, counted the same way,
42 // so a missing tap can be put on the right side of the bridge: none here
43 // means the app never handed it over, one here and none through onTap
44 // means the page's replay lost it.
45 var dispatchedTaps = 0
46 window.addEventListener('craftNotificationResponse', function () { dispatchedTaps++ })
47
3948 var NONCE = '__CRAFT_E2E_NONCE__'
4049 // Which platform the harness built this leg for. Substituted in from
4150 // outside, because the page comparing window.craft.platform against a
@@ -487,6 +496,40 @@
487496 setTimeout(report, 250)
488497 }
489498
499 // #255: a tap on a push that launches the app reaches a page that
500 // subscribes late, through notifications.onTap.
501 //
502 // The harness does on iOS what a person does, from an XCUITest: it opens
503 // the permission link and allows the prompt, kills the app, sends a real
504 // push with `simctl push`, and taps the banner. The page subscribes after
505 // the suite, seconds after the bridge appeared, and reports what it was
506 // handed. On any other launch it was handed nothing, and says so.
507 //
508 // Permission is asked for only when the link asks, because nothing
509 // answers the prompt on the launches simctl makes. iOS only: Android has
510 // no tap path to test yet.
511 function probeNotifications() {
512 if (window.craft.platform !== 'ios') return
513 var launch = dispatchedLinks.filter(function (detail) { return detail.initial === true })[0] || null
514 if (launch && launch.url.indexOf('://e2e/notify') !== -1) {
515 var said = function (text) { document.getElementById('notification-permission').textContent = 'CRAFT-E2E-NOTIFY-PERMISSION ' + text }
516 window.craft.permissions.request('notifications').then(said, function (error) { said('rejected ' + describeError(error).message) })
517 }
518 var onTap = window.craft.notifications && window.craft.notifications.onTap
519 var seen = { dispatched: 0, taps: [], onTap: typeof onTap, unsubscribe: null }
520 if (typeof onTap === 'function') {
521 seen.unsubscribe = typeof window.craft.notifications.onTap(function (detail) { seen.taps.push(detail || {}) })
522 }
523 // Long enough for a replay, or a second delivery, to have arrived.
524 setTimeout(function () {
525 seen.dispatched = dispatchedTaps
526 var line = 'CRAFT-E2E-NOTIFICATION ' + JSON.stringify(seen)
527 document.getElementById('notification').textContent = line
528 try { console.log(line) } catch (ignored) {}
529 try { if (window.craft && window.craft.log) window.craft.log(line) } catch (ignored) {}
530 }, 1500)
531 }
532
490533 function waitForBridge(attempt) {
491534 if (window.craft && window.craft.getDeviceInfo) return Promise.resolve(true)
492535 if (attempt >= 150) return Promise.resolve(false)
@@ -517,6 +560,7 @@
517560 emit({ event: 'done', passed: passed, failed: failed })
518561 document.getElementById('headline').textContent = failed ? 'FAILED' : 'PASSED'
519562 probeDeepLinks()
563 probeNotifications()
520564 return
521565 }
522566