Search code examples
swiftuilocalnotificationxcuitest

XCUITest - interacting with notification from lock screen


I am attempting to write a a UI test that taps on a delivered local notification after the device has been locked. I have been successful so far in tapping on a notification that was delivered on the springboard (when the device is already unlocked) but not from the lock screen. Does anyone know if this is possible?

Please note that this is different from questions such as this one, which merely hit the home button to leave the app under test and wait for the notification.

Here is the relevant portion of my test code:

// ...already did stuff to schedule a local notification...
// now lock screen
XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))
// set up query for notification then wait
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let notificationQuery : XCUIElementQuery = springboard
                    .otherElements["Notification"]
                    .descendants(matching: .any)
let notification = notificationQuery["MYAPP, now, My Notification Header, Notification message body."]
// fails
XCTAssertTrue(notification.waitForExistence(timeout: 60))

If I replace the call to

XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))

with

XCUIDevice.shared.press(.home)

then the test passes.

All suggestions appreciated!


Solution

  • I have similar issues, and I was able to resolve them by Adding a press lock Again. Here is the working code. I am using https://github.com/pterodactyl for Notifications. I wrote this code a couple of years back and still passing.

    I do the same thing twice and able to validate notifications. Once the device is locked. You will see a black screen like it is turned off, and the second time when you will send the same code, it will turn on the device, and you can get notifications element for tests

    // Lock the screen
    XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))
    sleep(1)

    // same command second time ,it will wake the screen
    XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))

    import PterodactylLib
    import XCTest
    
    func testRemotePush() {
        let app = XCUIApplication()
        app.launch()
        let pterodactyl = Pterodactyl(targetAppBundleId: "MOBILE APP BUNDLE ID")
        
        // did not find XCUI Protected Resources for Notifications
        // app.resetAuthorizationStatus(for: XCUIProtectedResource)
        
        XCTAssertTrue(
            app.buttons["loginButton"].waitForExistence(timeout: .superMaxTimeout),
            "Not able to launch App"
        )
        
        // Tap the home button
        XCUIDevice.shared.press(XCUIDevice.Button.home)
        sleep(1)
        
        // Trigger a push notification
        pterodactyl.triggerSimulatorNotification(withMessage: "Trust me ! I am notifications")
        sleep(1)
        
        // Lock the screen
        XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))
        sleep(1)
        // same command second time ,it will wake the screen
        
        XCUIDevice.shared.perform(NSSelectorFromString("pressLockButton"))
        
        // Tap the notification when it appears
        let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
        
        let notificationCell = springboard.buttons["NotificationCell"]
        XCTAssertTrue(notificationCell.waitForExistence(timeout: 150)) // implicity wait
        
        XCTAssertTrue(notificationCell.label.contains("Trust me ! I am notifications"))
    }