I'm implementing push notifications in an iOS app, and as I'm doing so, I want to write a UI test that verifies that the app does the correct thing when it is launched with a certain push notification payload (i.e. the app navigates to the correct table view and highlights the correct cell).
Can this be done? I can't seem to find anyone who has done this before or has asked this question before.
Thankful for any pointers.
Go to File > New > Target. Then, search for UI Testing Bundle. Select Unit Testing Bundle and then click Next. As UI tests take time, it is usually best to stop immediately when a failure occurs.
Push payloads are sent with encrypted content when the mobile app supplies an RSA public encryption key upon push registration with the Salesforce push notification service. When a payload is sent from a customer org to a user's device, the mobile app processes and decrypts the payload.
With Xcode 9 you can now actually test Remote Notification handling in a UITest. I implemented that using a framework called NWPusher
I wrote a long blogpost about my implementation and added a demo project to github.
Here is a short description of what I did:
Preparation
Write the Test
The test does the following steps:
In my demo the different types of notifications trigger differently colored modal View Controller in the app. So my test class looks like this
import XCTest
import PusherKit
class PushNotificationUITests: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
}
func testPushNotifications() {
let app = XCUIApplication()
app.launchArguments.append("isRunningUITests")
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
app.launch()
// dismiss the system dialog if it pops up
allowPushNotificationsIfNeeded()
// get the current deviceToken from the app
let deviceToken = app.staticTexts.element(matching: .any, identifier: "tokenLabel").label
// close app
XCUIDevice.shared.press(XCUIDevice.Button.home)
sleep(1)
// trigger red Push Notification
triggerPushNotification(
withPayload: "{\"aps\":{\"alert\":\"Hello Red\"}, \"vcType\":\"red\"}",
deviceToken: deviceToken)
// tap on the notification when it is received
springboard.otherElements["PUSHNOTIFICATION, now, Hello Red"].tap()
// check if the red view controller is shown
XCTAssert(app.staticTexts["Red"].exists)
// dismiss modal view controller and close app
app.buttons["Close"].tap()
XCUIDevice.shared.press(XCUIDevice.Button.home)
sleep(1)
// trigger green Push Notification
triggerPushNotification(
withPayload: "{\"aps\":{\"alert\":\"Hello Green\"}, \"vcType\":\"green\"}",
deviceToken: deviceToken)
// tap on the notification when it is received
springboard.otherElements["PUSHNOTIFICATION, now, Hello Green"].tap()
// check if the green view controller is shown
XCTAssert(app.staticTexts["Green"].exists)
// dismiss modal view controller and close app
app.buttons["Close"].tap()
XCUIDevice.shared.press(XCUIDevice.Button.home)
sleep(1)
// trigger blue Push Notification
triggerPushNotification(
withPayload: "{\"aps\":{\"alert\":\"Hello Blue\"}, \"vcType\":\"blue\"}",
deviceToken: deviceToken)
// tap on the notification when it is received
springboard.otherElements["PUSHNOTIFICATION, now, Hello Blue"].tap()
// check if the blue view controller is shown
XCTAssert(app.staticTexts["Blue"].exists)
// dismiss modal view controller
app.buttons["Close"].tap()
}
}
extension XCTestCase {
func triggerPushNotification(withPayload payload: String, deviceToken: String) {
let uiTestBundle = Bundle(for: PushNotificationUITests.self)
guard let url = uiTestBundle.url(forResource: "pusher.p12", withExtension: nil) else { return }
do {
let data = try Data(contentsOf: url)
let pusher = try NWPusher.connect(withPKCS12Data: data, password: "pusher", environment: .auto)
try pusher.pushPayload(payload, token: deviceToken, identifier: UInt(arc4random_uniform(UInt32(999))))
} catch {
print(error)
}
}
func allowPushNotificationsIfNeeded() {
addUIInterruptionMonitor(withDescription: "“RemoteNotification” Would Like to Send You Notifications") { (alerts) -> Bool in
if(alerts.buttons["Allow"].exists){
alerts.buttons["Allow"].tap();
}
return true;
}
XCUIApplication().tap()
}
}
This only works on a physical device, because remote notifications do not work in the simulator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With