feat(ios): add error handling and integration tests

Implement comprehensive error handling and integration test suite:

Error Handling (Section 8):
- Add iOS-specific error codes to DailyNotificationErrorCodes:
  - NOTIFICATION_PERMISSION_DENIED
  - PENDING_NOTIFICATION_LIMIT_EXCEEDED
  - BG_TASK_NOT_REGISTERED
  - BG_TASK_EXECUTION_FAILED
  - BACKGROUND_REFRESH_DISABLED
- Add helper methods for iOS-specific error responses
- Enhance error handling in ReactivationManager:
  - Database errors handled gracefully (non-fatal)
  - Notification center errors handled gracefully (non-fatal)
  - Scheduling errors handled gracefully (non-fatal)
  - All errors logged, app continues normally
  - Partial results returned when operations fail
- Update plugin methods to use iOS-specific error codes:
  - getNotificationPermissionStatus uses NOTIFICATION_PERMISSION_DENIED

Integration Tests (Section 9.2):
- Add DailyNotificationRecoveryIntegrationTests:
  - Full recovery flow tests (cold start, termination)
  - Error handling tests (database, notification center, scheduling)
  - App stability tests (no crashes, concurrent operations)
  - Partial recovery tests
  - Timeout handling tests
- Test coverage:
  - 10 integration tests covering recovery scenarios
  - Error handling verification
  - App stability verification
  - Concurrent operation safety

Completes sections 8.1, 8.2, and 9.2 of iOS implementation checklist.
This commit is contained in:
Matthew
2025-12-09 02:46:13 -08:00
parent 12d8536588
commit 3649e76c49
5 changed files with 650 additions and 29 deletions

View File

@@ -1290,6 +1290,17 @@ public class DailyNotificationPlugin: CAPPlugin {
let status = await scheduler.checkPermissionStatus()
// Map to iOS-specific error if denied
if status == .denied {
let error = DailyNotificationErrorCodes.notificationPermissionDenied()
let errorMessage = error["message"] as? String ?? "Notification permission denied"
let errorCode = error["error"] as? String ?? DailyNotificationErrorCodes.NOTIFICATION_PERMISSION_DENIED
DispatchQueue.main.async {
call.reject(errorMessage, errorCode)
}
return
}
let result: [String: Any] = [
"authorized": status == .authorized,
"denied": status == .denied,