Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XCUITest interact with a Notification Banner.

Is it possible in XCUITest to validate that a notification banner is sent to the screen?

I can add an accessibility identifier to the notification, but I am having a problem getting XCUITest to interact with it when the banner is ent to the screen. I know that XCUITest runs in a separate process from the app, but was wondeering if it was still possible to interact with the notification or is it beyond the scope of XCUITest?

Thanks,

like image 740
P. Lemelle Avatar asked Dec 14 '22 00:12

P. Lemelle


2 Answers

With Xcode 9 this is now possible. You can get access to other apps. That includes the springboard which contains the Notification banner.

XCUIApplication now has a new initializer that takes a bundle identifier as parameter. It gives you a reference to the app that uses that bundle identifier. You can then use the normal queries to access UI elements. Just like you did before with your own app.

This is a test that checks if a Local Notification is being displayed when the app is closed:

import XCTest

class UserNotificationUITests: XCTestCase {

    override func setUp() {
        super.setUp()
        continueAfterFailure = false
    }

    func testIfLocalNotificationIsDisplayed() {
        let app = XCUIApplication()
        let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")

        app.launch()

        // close app to trigger local notification
        XCUIDevice.shared.press(XCUIDevice.Button.home)

        // wait for the notification
        let localNotification = springboard.otherElements["USERNOTIFICATION, now, Buy milk!, Remember to buy milk from store!"]
        XCTAssertEqual(waiterResultWithExpectation(localNotification), XCTWaiter.Result.completed)
    }
}

extension UserNotificationUITests {
    func waiterResultWithExpectation(_ element: XCUIElement) -> XCTWaiter.Result {
        let myPredicate = NSPredicate(format: "exists == true")
        let myExpectation = XCTNSPredicateExpectation(predicate: myPredicate,
                                                      object: element)
        let result = XCTWaiter().wait(for: [myExpectation], timeout: 6)
        return result
    }
}

You can checkout the demo app including this test here

You can also test Remote Notifications with UITests. That's needs a bit more work, because you cannot directly schedule Remote Notifications from your code. You can use a service called NWPusher for that. I wrote a blogpost about how to test Remote Notifications with Xcode UITests and there also is a demo project on github.

like image 89
joern Avatar answered Dec 26 '22 11:12

joern


Xcode 12 iOS 14*

Also accessing/asserting inside the notification is possible:

let notification = springBoard.otherElements["Notification"].descendants(matching: .any)["APPNAME, now, TITLE, BODY"]
    if notification.waitForExistence(timeout: 10) {
        notification.tap()
    }
like image 41
Dimitar Stefanovski Avatar answered Dec 26 '22 10:12

Dimitar Stefanovski