also looking at this
fix(ios): schedule a notification with the data the page gave it
#262
8 files
+242
-22
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { describe, expect, it } from 'bun:test' |
| 2 | 2 | import { readFileSync } from 'node:fs' |
| 3 | 3 | import { join } from 'node:path' |
| 4 | import { ANDROID_DECLINE_PHRASES, androidDeclines, awaitedNeeds, deepLinkProblems, deepLinkReports, deepLinkResults, DISMISS_SHARE_MENU, elfSectionNames, evaluateRun, hasTerminated, NOTIFICATION_ROUTE, notificationBody, notificationPayload, notificationReceiptProblems, notificationReceiptReport, notificationTapProblems, notificationTapReport, parseDriverOutput, REQUIRED_CASES, requiredCaseProblems, runtimePermissionGranted, shareMenuInFront, strippedLibraryProblems, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol' | |
| 4 | import { ANDROID_DECLINE_PHRASES, androidDeclines, awaitedNeeds, deepLinkProblems, deepLinkReports, deepLinkResults, DISMISS_SHARE_MENU, elfSectionNames, evaluateRun, hasTerminated, localNotificationProblems, NOTIFICATION_ROUTE, notificationBody, notificationPayload, notificationReceiptProblems, notificationReceiptReport, notificationTapProblems, notificationTapReport, parseDriverOutput, REQUIRED_CASES, requiredCaseProblems, runtimePermissionGranted, shareMenuInFront, strippedLibraryProblems, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol' | |
| 5 | 5 | |
| 6 | 6 | const ESC = String.fromCharCode(27) |
| 7 | 7 | |
| @@ -435,6 +435,48 @@ describe('notification tap cold start', () => { | ||
| 435 | 435 | }) |
| 436 | 436 | }) |
| 437 | 437 | |
| 438 | describe('tap on a notification the page scheduled with data', () => { | |
| 439 | const RUN = 'craft-e2e-ios-runtime-1' | |
| 440 | const tap = { craftE2E: RUN, stage: 'local', nested: { kept: true } } | |
| 441 | const pushed = { craftE2E: RUN, stage: 'cold', route: NOTIFICATION_ROUTE } | |
| 442 | const output = (report: object) => [ | |
| 443 | `CRAFT-E2E-NOTIFICATION-RESULT CRAFT-E2E-NOTIFICATION ${JSON.stringify({ dispatched: 1, taps: [pushed], onTap: 'function', unsubscribe: 'function' })}`, | |
| 444 | `CRAFT-E2E-LOCAL-RESULT CRAFT-E2E-NOTIFICATION ${JSON.stringify(report)}`, | |
| 445 | ].join('\n') | |
| 446 | const judge = (report: object) => localNotificationProblems(notificationTapReport(output(report), 'CRAFT-E2E-LOCAL-RESULT'), RUN) | |
| 447 | ||
| 448 | it('passes a tap that hands back the data it was scheduled with, nested values included', () => { | |
| 449 | expect(judge({ dispatched: 1, taps: [tap], onTap: 'function', unsubscribe: 'function' })).toEqual([]) | |
| 450 | }) | |
| 451 | ||
| 452 | // The bug: neither scheduler set userInfo. | |
| 453 | it('fails a tap that hands the page {}', () => { | |
| 454 | expect(judge({ dispatched: 1, taps: [{}], onTap: 'function', unsubscribe: 'function' })) | |
| 455 | .toEqual(['a tap on a scheduled notification handed the page {}: the data it was scheduled with never reached userInfo']) | |
| 456 | }) | |
| 457 | ||
| 458 | it('fails lost nesting, another run\'s data, a double delivery, and a tap never dispatched', () => { | |
| 459 | expect(judge({ dispatched: 1, taps: [{ ...tap, nested: '[object Object]' }], onTap: 'function', unsubscribe: 'function' })[0]).toContain('nested data did not survive') | |
| 460 | expect(judge({ dispatched: 1, taps: [{ ...tap, craftE2E: 'an-earlier-run' }], onTap: 'function', unsubscribe: 'function' })[0]).toContain('expected the data it was scheduled with once') | |
| 461 | expect(judge({ dispatched: 1, taps: [tap, tap], onTap: 'function', unsubscribe: 'function' })[0]).toContain('expected the data it was scheduled with once') | |
| 462 | expect(judge({ dispatched: 0, taps: [], onTap: 'function', unsubscribe: 'function' })).toEqual(['the app never dispatched the tap on the scheduled notification']) | |
| 463 | }) | |
| 464 | ||
| 465 | it('reads each tap report by its own label', () => { | |
| 466 | // The push's report is not the scheduled notification's, and a run that | |
| 467 | // never got to the local stage has no local report at all. | |
| 468 | expect(notificationTapReport(output({ dispatched: 1, taps: [tap] }))?.taps).toEqual([pushed]) | |
| 469 | expect(notificationTapReport(output({ dispatched: 1, taps: [tap] }), 'CRAFT-E2E-LOCAL-RESULT')?.taps).toEqual([tap]) | |
| 470 | expect(localNotificationProblems(notificationTapReport(output({}).split('\n')[0]!, 'CRAFT-E2E-LOCAL-RESULT'), RUN)) | |
| 471 | .toEqual(['the tap on the scheduled notification never reported; see xcodebuild-notification.log']) | |
| 472 | }) | |
| 473 | ||
| 474 | it('finds the local banner by text the push banners do not share', () => { | |
| 475 | expect(notificationBody(RUN, 'local')).toBe(`${RUN} local`) | |
| 476 | expect(notificationBody(RUN, 'cold')).not.toContain(notificationBody(RUN, 'local')) | |
| 477 | }) | |
| 478 | }) | |
| 479 | ||
| 438 | 480 | describe('notification that arrives while the app is open', () => { |
| 439 | 481 | const RUN = 'craft-e2e-ios-shim-1' |
| 440 | 482 | const arrival = { aps: { alert: { title: 'Craft E2E', body: `${RUN} foreground` } }, craftE2E: RUN, stage: 'foreground', route: NOTIFICATION_ROUTE } |