appcues / appcues-ios-sdk

The Appcues iOS SDK
https://www.appcues.com/mobile
MIT License
8 stars 2 forks source link

Add push install verification to debugger #514

Closed mmaatttt closed 6 months ago

mmaatttt commented 6 months ago

I've been able to create a surprisingly full-featured push verification system for the debugger. And once we hook it up to the send test push API that can return some backend diagnostics, we should be able to provide one-tap E2E verification of an Appcues push setup.

PushVerifier is the doing all the heavy lifting. Since it has several dependencies and since PushMonitor needs to call the verifier, I've added it into the main DI container unlike APIVerifier and DeepLinkVerifier.

Overview of what's being verified (and how), corresponding to the Error numbers:

  1. Verify Appcues.setPushToken(:) is called. I could add an additional check that didRegisterForRemoteNotificationsWithDeviceToken is implemented, but these are tightly coupled, so it seems like overkill. The docs (when we write them) about these errors should make it clear.
  2. When the notification authorization status is .notDetermined. If this error occurs, if a second attempt to verify the status is made, we'll trigger the push notification permission prompt. This is intended to be a helpful way to test quickly without having to create a permission primer flow (since we want to encourage people to create such a flow and not hardcode a permission request).
  3. Push notification permission prompt was denied. User will need to use the system settings app to change the permissions.
  4. .ephemeral (app clip only) or unknown permission status. Should never happen.
  5. UNUserNotificationCenter.current().delegate is nil. It needs to be assigned—usually the value is the `AppDelegate. Without this value, we can't check anything else about the implementation. Note that this check isn't 100% accurate, since iOS requires that "You must assign your delegate object to the UNUserNotificationCenter object before your app finishes launching." (ref), but we're only checking it when the debugger action is triggered.
  6. userNotificationCenter(_:didReceive:withCompletionHandler:) is not implemented. The function is an optional method of UNUserNotificationCenterDelegate, so we need to check it's implemented. It's required to process the user's response to a delivered notification.
  7. Verifies that the completion handler in userNotificationCenter(_:didReceive:withCompletionHandler:) isn't called more than once. I added this because the Appcues handler calls it if the SDK handles the response, but the app might call it too. I'm not sure the consequences of multiple completions, but better safe than sorry.
  8. Verify the user response is passed to Appcues.didReceiveNotification(response:completionHandler:). We generate a synthetic response object (approach reference) that matches our push payload (with the addition of _appcues_internal: true) to call the response handler. This is super handy since it removes the need for the user to actually tap on the incoming notification to verify this part of the system.

Errors 10/11 are internal to the test loop.

Once the backend push test endpoint is implemented, we'll call that and display any diagnostics that are returned.

mmaatttt commented 6 months ago

should we also verify userNotificationCenter(_:willPresent:withCompletionHandler:) for foreground push handling?

Good idea. I'll look into adding more functionality in a future pass!