addUIInterruptionMonitor is not getting called on macOS

Viewed 1380

I want to test my macOS application. It uses your Macbook's camera, and want to handle this in my UITest. However I cannot get it working. Here is my NOT working code. This code triggers to notification, and I'm presented an alert to allow access to my camera, but the closure is not getting called. Thanks fo any help.

There are many solutions for iOS, but I need it on macOS.

let alertHandler = addUIInterruptionMonitor(withDescription: "Camera Permission Alert") { (alert) -> Bool in
        if alert.buttons.matching(identifier: "OK").count > 0 {
           alert.buttons["OK"].click()
            self.app.click()
            return true
        } else {
            return false
        }
    }

    XCTAssertTrue(startButton.waitForExistence(timeout: 1.0))
    startButton.click()

    XCTAssertTrue(recordButton.waitForExistence(timeout: 20.0))
    recordButton.click()
    wait(for: 8)
    recordButton.click()
    removeUIInterruptionMonitor(alertHandler)
}
1 Answers

I managed to make interruption monitor work on macOS by adding an extra interaction after the interaction that triggers the system dialog (be it camera access or else). So in your example I would add an action after startButton.click() (if that is what triggers the camera access dialog).

Example:

func testCamera() {
    let alertHandler = addUIInterruptionMonitor(withDescription: "Camera Permission Alert") { (alert) -> Bool in
        if alert.buttons.matching(identifier: "OK").count > 0 {
           alert.buttons["OK"].click()
            self.app.click()
            return true
        } else {
            return false
        }
    }

    useCameraButton.click()

    // try to interact with the app by clicking on the app's window
    app.windows.first().click()
    // at this point the handler should intercept the system interruption 
    // and blocks further execution until handler does return

    // try to use the camera again
    useCameraButton.click()

    removeUIInterruptionMonitor(alertHandler)
}

Hint about this behaviour in Apple's documentation:

When an alert or other modal UI is an expected part of the test workflow, don't write a UI interruption monitor. The test won’t use the monitor because the modal UI isn’t blocking the test. A UI test only tries its UI interruption monitors if the elements it needs to interact with to complete the test are blocked by an interruption from an unrelated UI.

https://developer.apple.com/documentation/xctest/xctestcase/handling_ui_interruptions

Related