Add three test buttons (Empty, Invalid, Negative) below the "Test Notification"
button to test invalid time format handling. Each button attempts to schedule
a notification with invalid values: empty string, "25:00" (invalid hour), and
"-1:30" (negative time).
Improve TEST 3 error detection in test-phase1.sh by:
- Making grep case-insensitive to catch ERROR/invalid patterns
- Adding DNP-* error prefix patterns for plugin error logs
- Documenting that Capacitor bridge errors (⚡️ logs) appear in Xcode console
but not in system logs captured by xcrun simctl
The script was using 'local' keyword outside of function scope,
which caused "local: can only be used in a function" error when
running test-phase2.sh. Removed 'local' from three variable
assignments (device_id and logs) at script top level, as 'local'
is only valid inside functions in bash/zsh.
- Fix getNextNotificationTime() to find earliest scheduled notification
instead of using first request (pendingNotificationRequests doesn't
guarantee order)
- Add comprehensive logging for rollover tracking with DNP-ROLLOVER
prefix for Xcode console filtering
- Reset all notifications and rollover state when scheduling new
notification via scheduleDailyNotification() to ensure clean test
state
- Fix userInfo scope error in handleNotificationDelivery error handler
- Update test app UI to refresh status every 5-10 seconds and
immediately after notification delivery to reflect rollover changes
- Add console logging in UI to debug getNotificationStatus() results
This ensures the UI correctly displays the next notification time after
rollover completes, and test notifications start with a clean slate.
Fixed multiple issues in iOS test script and added logging for test compatibility:
Test Script Fixes:
- Fixed get_simulator_id() to correctly extract UUID from booted devices
- Fixed get_app_logs() to use log show (historical) instead of log stream (live) to avoid hanging
- Improved check_plugin_configured() with multiple detection methods (app container, app listing, data directory)
- Added ensure_plugin_configured() function matching Android pattern for consistent user interaction flow
- Fixed integer comparison error in booted device check (removed newlines from count)
- Removed 'local' keyword from variables in main script body (local can only be used in functions)
- Fixed APP_BUNDLE_ID to match actual bundle identifier
Pending Notification Detection:
- Improved get_pending_notifications() to parse pendingCount from plugin logs
- Added direct log query without restrictive predicate to catch plugin logs
- Added multiple fallback methods for detecting pending count
Plugin Logging Enhancement:
- Added explicit pendingCount logging in DailyNotificationScheduler after scheduling
- Uses both NSLog() and print() to ensure logs appear in system logs and Xcode console
- Matches Android's alarm count logging pattern for test script compatibility
This resolves script crashes and enables reliable detection of pending notifications
for automated testing.
Fixed Swift compilation errors preventing iOS build:
- Added explicit self capture [self] in closures in DailyNotificationReactivationManager
- Removed invalid BGTaskScheduler.shared.registeredTaskIdentifiers API call
- Fixed initialization order in DailyNotificationModel (verifyEntities after container init)
Added missing configureNativeFetcher method to iOS plugin:
- Implemented method matching Android functionality
- Stores configuration in UserDefaults for persistence
- Registered method in pluginMethods array
- Supports both jwtToken and jwtSecret parameters for compatibility
This resolves the runtime error "configureNativeFetcher is not a function"
that was preventing the test app from configuring the plugin.
Adds complete iOS documentation suite to support iOS implementation
parity with Android features. Includes implementation directives,
recovery scenario mappings, database migration guide, troubleshooting
guide, and test scripts.
New Documentation:
- iOS Implementation Directive: Phase-based implementation guide
mirroring Android structure with iOS-specific considerations
- iOS Recovery Scenario Mapping: Maps Android recovery scenarios
to iOS equivalents with detection logic comparisons
- iOS Core Data Migration Guide: Complete Room → Core Data entity
mappings with implementation checklist for missing entities
- iOS Troubleshooting Guide: Common issues, debugging techniques,
and error code reference
Enhanced Documentation:
- API.md: Added iOS-only methods (permissions, background tasks,
pending notifications), platform differences table, and iOS-specific
error types. Updated version to 2.3.0.
Test Infrastructure:
- iOS test scripts for Phase 1 (cold start), Phase 2 (termination),
and Phase 3 (boot recovery) testing scenarios
All documentation addresses gaps identified in iOS Implementation
Documentation Review and provides foundation for iOS recovery feature
implementation (currently pending).
Note: iOS recovery features (ReactivationManager, scenario detection)
are NOT yet implemented. Documentation is ready to guide implementation.
Replace if let binding with boolean is check for CAPBridgedPlugin
conformance test. This eliminates the compiler warning about unused
variable 'capacitorPluginType' while maintaining the same diagnostic
functionality.
Fix configure() method to read parameters directly from CAPPluginCall
instead of expecting nested options object, matching Android implementation.
Improve build process to ensure canonical UI is always copied:
- iOS build script: Copy www/index.html to test app before build
- Android build.gradle: Add copyCanonicalUI task to run before build
- Ensures test apps always use latest UI from www/index.html
This fixes the issue where configure() was returning 'Configuration
options required' error because it expected a nested options object
when Capacitor passes parameters directly on the call object.
Implement UNUserNotificationCenterDelegate in AppDelegate to display
notifications when app is in foreground. Add visual feedback indicator
in test app UI to confirm notification delivery.
Changes:
- AppDelegate: Conform to UNUserNotificationCenterDelegate protocol
- AppDelegate: Implement willPresent and didReceive delegate methods
- AppDelegate: Set delegate at multiple lifecycle points to ensure
it's always active (immediate, after Capacitor init, on app active)
- UI: Add notification received indicator in status card
- UI: Add periodic check for notification delivery (every 5 seconds)
- UI: Add instructions on where to look for notification banner
- Docs: Add IOS_LOGGING_GUIDE.md for debugging iOS logs
This fixes the issue where scheduled notifications were not visible
when the app was in the foreground. The delegate method now properly
presents notifications with banner, sound, and badge options.
Verified working: Logs show delegate method called successfully when
notification fires, with proper presentation options set.
Fixed iOS 13.0 compatibility issue in test harness by replacing Logger
(iOS 14+) with os_log (iOS 13+). Fixed build script to correctly detect
and sync Capacitor config from App subdirectory. Unified both Android
and iOS test app UIs to use www/index.html as the canonical source.
Changes:
- DailyNotificationBackgroundTaskTestHarness: Replace Logger with os_log
for iOS 13.0 deployment target compatibility
- build-ios-test-app.sh: Fix Capacitor sync path detection to check
both current directory and App/ subdirectory for config files
- test-apps: Update both Android and iOS test apps to use www/index.html
as the canonical UI source for consistency
This ensures the plugin builds on iOS 13.0+ and both test apps provide
the same testing experience across platforms.
Capacitor iOS was not discovering DailyNotificationPlugin because it did not
conform to the CAPBridgedPlugin protocol required for runtime discovery.
Changes:
- Add @objc extension to DailyNotificationPlugin implementing CAPBridgedPlugin
with identifier, jsName, and pluginMethods properties
- Force-load plugin framework in AppDelegate before Capacitor initializes
- Remove duplicate BGTaskScheduler registration from AppDelegate (plugin handles it)
- Update podspec to use dynamic framework (static_framework = false)
- Add diagnostic logging to verify plugin discovery
Result: Plugin is now discovered by Capacitor and all methods are accessible
from JavaScript. Verified working with checkPermissionStatus() method.
Files modified:
- ios/Plugin/DailyNotificationPlugin.swift: Added CAPBridgedPlugin extension
- test-apps/ios-test-app/ios/App/App/AppDelegate.swift: Force-load + diagnostics
- ios/DailyNotificationPlugin.podspec: Dynamic framework setting
- doc/directives/0003-iOS-Android-Parity-Directive.md: Documented solution