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/protocol.test.tsmodified+50-1
Changes to scripts/mobile-e2e/protocol.test.ts
@@ -1,7 +1,7 @@
11import { describe, expect, it } from 'bun:test'
22import { readFileSync } from 'node:fs'
33import { join } from 'node:path'
4import { ANDROID_DECLINE_PHRASES, androidDeclines, awaitedNeeds, deepLinkProblems, deepLinkReports, deepLinkResults, DISMISS_SHARE_MENU, elfSectionNames, evaluateRun, hasTerminated, parseDriverOutput, REQUIRED_CASES, requiredCaseProblems, runtimePermissionGranted, shareMenuInFront, strippedLibraryProblems, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol'
4import { ANDROID_DECLINE_PHRASES, androidDeclines, awaitedNeeds, deepLinkProblems, deepLinkReports, deepLinkResults, DISMISS_SHARE_MENU, elfSectionNames, evaluateRun, hasTerminated, NOTIFICATION_ROUTE, notificationPayload, notificationTapProblems, notificationTapReport, parseDriverOutput, REQUIRED_CASES, requiredCaseProblems, runtimePermissionGranted, shareMenuInFront, strippedLibraryProblems, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol'
55
66const ESC = String.fromCharCode(27)
77
@@ -382,6 +382,55 @@ describe('cold-start deep links', () => {
382382 })
383383})
384384
385describe('notification tap cold start', () => {
386 const RUN = 'craft-e2e-ios-shim-1'
387 const line = (report: object) => `CRAFT-E2E-NOTIFICATION-RESULT CRAFT-E2E-NOTIFICATION ${JSON.stringify(report)}`
388 const tap = { aps: { alert: { title: 'Craft E2E', body: RUN } }, craftE2E: RUN, route: NOTIFICATION_ROUTE }
389 const judge = (report: object) => notificationTapProblems(notificationTapReport(`Test Case started.\n${line(report)}\n** TEST SUCCEEDED **`), RUN)
390
391 it('passes a late subscriber handed the tap that launched the app, once', () => {
392 expect(judge({ dispatched: 1, taps: [tap], onTap: 'function', unsubscribe: 'function' })).toEqual([])
393 })
394
395 // The two halves of #255, told apart.
396 it('blames native code when the app never dispatched the tap', () => {
397 expect(judge({ dispatched: 0, taps: [], onTap: 'function', unsubscribe: 'function' }))
398 .toEqual(['the app never dispatched the tap that launched it; native code dropped it before the page existed'])
399 })
400
401 it('blames the page when the tap was dispatched before anyone subscribed', () => {
402 const problems = judge({ dispatched: 1, taps: [], onTap: 'function', unsubscribe: 'function' })
403 expect(problems).toHaveLength(1)
404 expect(problems[0]).toContain('subscribed to notifications.onTap after launch was handed []')
405 })
406
407 it('fails a tap handed over twice, one from another run, or one that lost its route', () => {
408 expect(judge({ dispatched: 1, taps: [tap, tap], onTap: 'function', unsubscribe: 'function' })[0]).toContain('expected the tap that launched the app once')
409 expect(judge({ dispatched: 1, taps: [{ ...tap, craftE2E: 'an-earlier-run' }], onTap: 'function', unsubscribe: 'function' })[0]).toContain('expected the tap that launched the app once')
410 expect(judge({ dispatched: 1, taps: [{ ...tap, route: undefined }], onTap: 'function', unsubscribe: 'function' })[0]).toContain('without the push\'s route')
411 })
412
413 it('fails a bridge with no onTap, or one that returns no way to unsubscribe', () => {
414 expect(judge({ dispatched: 1, taps: [], onTap: 'undefined', unsubscribe: null }))
415 .toEqual(['notifications.onTap is undefined, so a page has no way to be handed a tap'])
416 expect(judge({ dispatched: 1, taps: [tap], onTap: 'function', unsubscribe: 'undefined' }))
417 .toEqual(['notifications.onTap returned undefined, expected a function that unsubscribes'])
418 })
419
420 it('names a run that never reported', () => {
421 expect(notificationTapProblems(notificationTapReport('** TEST FAILED **'), RUN, 'ios-shim/xcodebuild-notification.log'))
422 .toEqual(['the notification tap cold start never reported; see ios-shim/xcodebuild-notification.log'])
423 })
424
425 it('sends a push simctl accepts, whose body is the run the banner is found by', () => {
426 const payload = notificationPayload(RUN)
427 expect(new TextEncoder().encode(payload).length).toBeLessThanOrEqual(4096)
428 const parsed = JSON.parse(payload)
429 expect(parsed.aps.alert.body).toBe(RUN)
430 expect(parsed).toMatchObject({ craftE2E: RUN, route: NOTIFICATION_ROUTE })
431 })
432})
433
385434describe('cold-start deep links on Android', () => {
386435 const LINK = 'crafte2eprobe://e2e/cold?run=craft-e2e-android-shim-1'
387436 const report = { launch: `${LINK}&receive=subscribe`, receive: 'subscribe', onLink: [{ url: `${LINK}&receive=subscribe`, initial: true }], initialURL: null, unsubscribe: 'function' }