How to wait for Location Alert ( which is system alert) to show?

1.8k views Asked by At

I figured out how to dismiss System alert, but I am not able to wait for it to show , since app doesn't see System Alerts. I tried to debug with app.debugDescription and app.alerts.count but no luck.

2

There are 2 answers

0
Oletha On BEST ANSWER

Use addUIInterruptionMonitor:withDescription:handler: to register an interruption monitor. To 'wait' for the system alert to appear, use the handler to set a variable when it has been dealt with, and execute a benign interaction with the app when you want to wait for the alert.

You must continue to interact with the app while you are waiting, as interactions are what trigger interruption monitors.

class MyTests: XCTestCase {

    let app = XCUIApplication()

    func testLocationAlertAppears() {
        var hasDismissedLocationAlert = false
        let monitor = addUIInterruptionMonitor(withDescription: "LocationPermissions") { (alert) in
            // Check this alert is the location alert
            let location = NSPredicate(format: "label CONTAINS 'Location'")
            if alert.staticTexts.element(matching: location).exists {
                // Dismiss the alert
                alert.buttons["Allow"].tap()
                hasDismissedLocationAlert = true
                return true
            }
            return false
        }

        // Wait for location alert to be dismissed
        var i = 0
        while !hasDismissedLocationAlert && i < 20 {
            // Do some benign interaction
            app.tap()
            i += 1
        }

        // Clean up
        removeUIInterruptionMonitor(monitor)

        // Check location alert was dismissed
        XCTAssertTrue(hasDismissedLocationAlert)
    }
}
0
Michał Myśliwiec On

You should use addUIInterruptionMonitor as @Oletha wrote.

The tricky part here is that system alert buttons don't use Accessibility Identifiers so you have to search for text to tap them. This text is translated to the language you're running your simulator/device, which can be hard if you want to run the test for several languages beside English.

You could use AutoMate framework to simplify this. Here you have an example how to deal with system alerts using AutoMate:

func locationWhenInUse() {
    let token = addUIInterruptionMonitor(withDescription: "Location") { (alert) -> Bool in
        guard let locationAlert = LocationWhenInUseAlert(element: alert) else {
            XCTFail("Cannot create LocationWhenInUseAlert object")
            return false
        }

        locationAlert.allowElement.tap()
        return true
    }

    // Interruption won't happen without some kind of action.
    app.tap()
    // Wait for given element to appear
    wait(forVisibilityOf: locationPage.requestLabel)
    removeUIInterruptionMonitor(token)
}

In the example above the locationAlert.allowElement.tap() is possible because AutoMate can handle any language supported by iOS Simulator.

For more examples on how to deal with system alerts using AutoMate please look into: PermissionsTests.swift