From d7a2dbb9fd6d4863425cf8c8f61e8d68a5ca2379 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 16 Nov 2025 21:53:56 -0800 Subject: [PATCH] docs(ios): update test app docs with recent implementation details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated iOS test app documentation to reflect recent implementation work: channel methods, permission methods, BGTaskScheduler simulator limitation, and plugin discovery troubleshooting. Changes: - Added channel methods (isChannelEnabled, openChannelSettings) to UI mapping - Fixed permission method name (requestPermissions → requestNotificationPermissions) - Added checkPermissionStatus to UI mapping - Added Channel Management section explaining iOS limitations - Added BGTaskScheduler simulator limitation documentation (Code=1 is expected) - Added plugin discovery troubleshooting section (CAPBridgedPlugin conformance) - Added permission and channel methods to behavior classification table - Updated Known OS Limitations with simulator-specific BGTaskScheduler behavior Files modified: - doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md: UI mapping, debugging scenarios - doc/test-app-ios/IOS_PREFETCH_TESTING.md: Known limitations, behavior classification --- doc/test-app-ios/IOS_PREFETCH_TESTING.md | 14 ++++++++ doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md | 33 ++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/doc/test-app-ios/IOS_PREFETCH_TESTING.md b/doc/test-app-ios/IOS_PREFETCH_TESTING.md index 3c43372..49a8707 100644 --- a/doc/test-app-ios/IOS_PREFETCH_TESTING.md +++ b/doc/test-app-ios/IOS_PREFETCH_TESTING.md @@ -301,11 +301,22 @@ When you see `[DNP-FETCH] Fetch success (status=200, bytes=1234, ttl=86400)`, th **Critical:** These are iOS system limitations, not plugin bugs. If these conditions occur, it is **not a plugin bug**; confirm logs and document behavior. +**BGTaskScheduler Simulator Limitation:** +- **BGTaskSchedulerErrorDomain Code=1 (notPermitted) is EXPECTED on simulator** +- BGTaskScheduler doesn't work reliably on iOS Simulator - this is a known iOS limitation +- Background fetch scheduling will fail on simulator with Code=1 error +- **This is NOT a plugin bug** - notification scheduling still works correctly +- Prefetch won't run on simulator, but will work on real devices with Background App Refresh enabled +- Error handling logs: "Background fetch scheduling failed (expected on simulator)" +- **Testing:** Use Xcode → Debug → Simulate Background Fetch for simulator testing +- **See also:** `doc/directives/0003-iOS-Android-Parity-Directive.md` for implementation details + **iOS may NOT run BGTasks if:** - App has been force-quit by the user (iOS won't run BGTask for force-quit apps) - Background App Refresh is disabled in Settings → [Your App] - Device is in Low Power Mode and idle - Device battery is critically low +- **On Simulator:** BGTaskScheduler generally doesn't work (Code=1 error is expected) **iOS timing heuristics:** - iOS may delay or batch tasks; prefetch might run **much later** than `earliestBeginDate` (up to 15+ minutes) @@ -432,6 +443,7 @@ When everything is wired correctly, one full cycle should produce: - Check BGTaskScheduler submission succeeded - Verify `earliestBeginDate` is at least 1 minute in future - Check for BGTaskScheduler errors in logs +- **On Simulator:** BGTaskSchedulerErrorDomain Code=1 (notPermitted) is expected - see "Known OS Limitations" **If you see BGTask scheduled but not persisted:** - Check database write operations @@ -522,6 +534,8 @@ Testable matrix of deterministic vs heuristic behavior: |--------|-------------------|----------------|---------|-------| | A | `BGTaskScheduler.shared.register` | Yes | Sim + Dev | Registration must always log & succeed/fail deterministically | | A | `configure()`, `getLastNotification()`, `cancelAllNotifications()`, `getNotificationStatus()`, `updateSettings()` | Yes | Sim + Dev | Logic & I/O-only, no timing dependencies | +| A | `checkPermissionStatus()`, `requestNotificationPermissions()` | Yes | Sim + Dev | Permission state reading and requests, deterministic | +| A | `isChannelEnabled(channelId?)`, `openChannelSettings(channelId?)` | Yes | Sim + Dev | Channel status and settings (iOS: app-wide, not per-channel) | | A | `getBatteryStatus()`, `getPowerState()`, `getRollingWindowStats()` | Yes | Sim + Dev | State reading, deterministic | | A | `testJWTGeneration()`, `testEndorserAPI()` | Yes | Sim + Dev | API call logic, deterministic | | A | Fetch function logic (HTTP calls, DB writes, JSON parsing) | Yes | Sim + Dev | Code path is deterministic | diff --git a/doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md b/doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md index f969b0d..2cf80fe 100644 --- a/doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md +++ b/doc/test-app-ios/IOS_TEST_APP_REQUIREMENTS.md @@ -69,6 +69,7 @@ The iOS test app **MUST** use the same HTML/JS UI as the Android test app to ens - Test notification button - Check permissions button - Request permissions button +- Channel management buttons (Check Channel Status, Open Channel Settings) - Status display area - Log output area (optional, for debugging) @@ -86,12 +87,17 @@ The test app UI must support: - Check permissions button - Show ✅/❌ indicators for each permission -3. **Notification Testing** +3. **Channel Management** (iOS parity with Android) + - Check channel status button (iOS: checks app-wide notification authorization) + - Open channel settings button (iOS: opens app Settings, not per-channel) + - Note: iOS doesn't have per-channel control like Android; these methods provide app-wide equivalents + +4. **Notification Testing** - Schedule test notification button - Display scheduled time - Show notification status -4. **Status Display** +5. **Status Display** - Show last notification time - Show pending notification count - Display error messages if any @@ -101,12 +107,14 @@ The test app UI must support: | UI Element / Button | Plugin Method / API Call | Notes | |---------------------|-------------------------|-------| | "Check Plugin Status" | `DailyNotification.configure()` or status call | Verify plugin load & config | -| "Check Permissions" | `getNotificationStatus()` | Maps to permission state | -| "Request Permissions" | `requestPermissions()` | Drives iOS UNUserNotificationCenter | +| "Check Permissions" | `checkPermissionStatus()` | Returns current notification permission status | +| "Request Permissions" | `requestNotificationPermissions()` | Requests notification permissions (shows system dialog) | | "Schedule Test Notification" | `scheduleDailyNotification()` | Should schedule prefetch + notify | | "Show Last Notification" | `getLastNotification()` | Uses deterministic path (Bucket A) | | "Cancel All Notifications" | `cancelAllNotifications()` | Uses deterministic path (Bucket A) | | "Get Notification Status" | `getNotificationStatus()` | Uses deterministic path (Bucket A) | +| "Check Channel Status" | `isChannelEnabled(channelId?)` | Checks if notifications enabled (iOS: app-wide) | +| "Open Channel Settings" | `openChannelSettings(channelId?)` | Opens notification settings (iOS: app Settings) | **See `IOS_PREFETCH_TESTING.md` Behavior Classification for deterministic vs heuristic methods.** @@ -291,7 +299,22 @@ e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWith - Check notification category registered - **See also:** `IOS_PREFETCH_TESTING.md – Log Checklist: Section 4` -3. **Build Failures:** +3. **BGTaskScheduler Fails on Simulator:** + - **Expected Behavior:** BGTaskSchedulerErrorDomain Code=1 (notPermitted) is **normal on simulator** + - BGTaskScheduler doesn't work reliably on simulator - this is an iOS limitation, not a plugin bug + - Notification scheduling still works; prefetch won't run on simulator but will work on real devices + - Error handling logs clear message: "Background fetch scheduling failed (expected on simulator)" + - **See also:** `IOS_PREFETCH_TESTING.md – Known OS Limitations` for details + - **Testing:** Use Xcode → Debug → Simulate Background Fetch for simulator testing + +4. **Plugin Not Discovered:** + - Check plugin class conforms to `CAPBridgedPlugin` protocol (required for Capacitor discovery) + - Verify `@objc extension DailyNotificationPlugin: CAPBridgedPlugin` exists in plugin code + - Check plugin framework is force-loaded in AppDelegate before Capacitor initializes + - Verify `pluginMethods` array includes all `@objc` methods + - **See also:** `doc/directives/0003-iOS-Android-Parity-Directive.md – Plugin Discovery Issue` for detailed troubleshooting + +5. **Build Failures:** - Run `pod install` - Clean build folder (Cmd+Shift+K) - Verify Capacitor plugin path