I would like to write a test like so:
When my app goes to a certain pane, it should request permission to use the camera.
I want to test whether or not the pane appears. I am using XC's builtin UITest framework to do this. Per what I found on google and here, it seems like I should do the following:
let dialogAppearedExpectation = expectationWithDescription("Camera Permission Dialog Appears")
addUIInterruptionMonitorWithDescription("Camera Permission Alert") { (alert) -> Bool in
dialogAppearedExpectation.fulfill()
return true
}
goToCameraPage()
waitForExpectationsWithTimeout(10) { (error: NSError?) -> Void in
print("Error: \(error?.localizedDescription)")
}
The test began with failing, great. I implemented goToCameraPage, which correctly causes the "give permission" popup to appear. However, I would expect this to trigger the interruption monitor. No such interruption is caught, however, and fulfillment does not occur.
I read somewhere that you should do app.tap()
after the dialog appears. However, when I do that, it clicks the "allow" button. The dialog disappears and still no interruption is handled.
Is there some way in which permission dialogs are not considered "alerts" or can't be handled? I even went in and replaced the interruption bit with a thing which just looks at app.alerts
, but that turns out to be empty, even as I'm looking right at the popup in Simulator.
Thanks! I am using Xcode7.2, iOS 9.2 simulator for iPhone 6s.
I have noticed this problem as well. It seems like the interruption handlers are run asynchronously and there is no way to assert whether they were called. Also waiting for an expectation seems to prevent the interruption monitor from running at all. It looks like the system is waiting for the expectation to fulfil and the expectation is waiting for the the interruption monitor to fire. A classic case of deadlock.
However, I have found a rather quirky solution that uses NSPredicate
-based expecations:
var didShowDialog = false
expectation(for: NSPredicate() {(_,_) in
XCUIApplication().tap() // this is the magic tap that makes it work
return didShowDialog
}, evaluatedWith: NSNull(), handler: nil)
addUIInterruptionMonitor(withDescription: "Camera Permission Alert") { (alert) -> Bool in
alert.buttons.element(boundBy: 0).tap() // not sure if allow = 0 or 1
didShowDialog = true
return true
}
goToCameraPage()
waitForExpectations(timeout: 10) { (error: Error?) -> Void in
print("Error: \(error?.localizedDescription)")
}
Apparently, doing the XCUIApplication().tap()
inside the predicate block somehow allows the interruption monitor to be run, even though the test case is waiting for an expectation.
I hope this works as well for you as it did for me!