ReviewOS

also looking at this

craft-native/craft

test(ios): verify app termination before local notification delivery

#308
Merged glennmichael123 wants to merge codex/ios-notification-deadline into main
5 files +96 -21
scripts/mobile-e2e/ios.tsmodified+4-9
Changes to scripts/mobile-e2e/ios.ts
@@ -3,7 +3,7 @@ import type { LegOutcome, RunnerOptions } from './types'
33import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
44import { join } from 'node:path'
55import { bootSimulator, init, pickSimulator } from '../../packages/ios/src/index'
6import { deepLinkProblems, deepLinkResults, evaluateRun, hasTerminated, localNotificationProblems, notificationBody, notificationPayload, notificationReceiptProblems, notificationReceiptReport, notificationTapProblems, notificationTapReport, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol'
6import { deepLinkProblems, deepLinkResults, evaluateRun, hasTerminated, LOCAL_NOTIFICATION_DELAY_MS, localNotificationProblems, NOTIFICATION_TEST_TIMEOUT_MS, notificationBody, notificationPayload, notificationReceiptProblems, notificationReceiptReport, notificationTapProblems, notificationTapReport, ZIG_REFUSED_ACTIONS, ZIG_SERVED_ACTIONS, ZIG_TESTED_ACTIONS, zigDispatchedActions, zigHandBacks, zigRefusals } from './protocol'
77import { command, driverPage, waitForFile } from './support'
88
99/** The scheme the probe registers, and the one its cold-start link uses. */
@@ -69,13 +69,6 @@ const UI_TESTS = `${APP_NAME}UITests`
6969/** The UI test classes, each run on its own with `-only-testing`. */
7070const UI_TEST_CLASSES = ['DeepLinkColdStartTests', 'NotificationTapColdStartTests'] as const
7171
72/**
73 * How long the notification UI test gets in all. It starts a test runner,
74 * launches the app four times, answers a permission prompt and waits out a
75 * scheduled notification; it usually takes about a minute.
76 */
77const NOTIFICATION_TEST_TIMEOUT_MS = 300_000
78
7972/**
8073 * The pushes the notification UI test has asked for, in order, one per
8174 * `CRAFT-E2E-PUSH-READY <stage>` line.
@@ -343,7 +336,7 @@ schemes:
343336 TEST_RUNNER_PROBE_BUNDLE_ID: BUNDLE_ID,
344337 TEST_RUNNER_PROBE_NOTIFY_LINK: `${DEEP_LINK_SCHEME}://e2e/notify?run=${encodeURIComponent(nonce)}`,
345338 TEST_RUNNER_PROBE_PUSH_BODY: notificationBody(nonce, 'cold'),
346 TEST_RUNNER_PROBE_LOCAL_LINK: `${DEEP_LINK_SCHEME}://e2e/local?run=${encodeURIComponent(nonce)}`,
339 TEST_RUNNER_PROBE_LOCAL_LINK: `${DEEP_LINK_SCHEME}://e2e/local?run=${encodeURIComponent(nonce)}&delayMs=${LOCAL_NOTIFICATION_DELAY_MS}`,
347340 TEST_RUNNER_PROBE_LOCAL_BODY: notificationBody(nonce, 'local'),
348341 },
349342 stdin: 'ignore',
@@ -365,6 +358,8 @@ schemes:
365358 }
366359 if (tapping.exitCode === null) tapping.kill()
367360 await tapping.exited
361 if (tapping.exitCode !== 0)
362 failures.push(`notification UI test exited ${tapping.exitCode}; see ${notificationEvidence}`)
368363 await command(['xcrun', 'simctl', 'io', device.udid, 'screenshot', join(evidence, 'notification-screen.png')], { allowFailure: true })
369364 await command(['xcrun', 'simctl', 'terminate', device.udid, BUNDLE_ID], { allowFailure: true })
370365 const notificationOutput = readFileSync(notificationLog, 'utf8')