Reputation: 3241
I'm working on a UI unit test for my app, and am trying to figure out how to automatically have the test framework click "OK" when the system presents an alert asking for permission to access contacts.
So far, I've looked at these four SO posts, and tried the various suggestions, but am still unable to get this to work:
XCTest app tests and permissions alerts
Xcode 7 UI Testing: how to dismiss a series of system alerts in code
Xcode UI Testing allow system alerts series
Xcode 7 UI Testing: Dismiss Push and Location alerts
Here's what I currently am trying - however, the permissions dialog is still not being automatically accepted; the test waits for me to click "OK" before moving forward: func testApp() {
self.addUIInterruptionMonitor(withDescription: "MyDescription", handler: { (alert) -> Bool in
let button = alert.buttons["OK"]
if button.exists {
button.tap()
return true
}
return false
})
let app = XCUIApplication()
app.launch()
...
app.tap()
...
}
EDIT: Here's the change I've made based on @ad-johnson's suggestion:
var app: XCUIApplication!
override func setUp() {
super.setUp()
continueAfterFailure = false
app = XCUIApplication()
addUIInterruptionMonitor(withDescription: "Contact Auth")
{ (alert) -> Bool in if alert.buttons["OK"].exists {
alert.buttons["OK"].tap()
}
return true }
app.launch()
}
func testScreenshots() {
app.tap()
...
}
Upvotes: 4
Views: 5376
Reputation: 12011
I tried addUIInterruptionMonitor
many times and it never works. Access directly to the button through the Sprignboard app proxy:
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let okBtn = springboard.buttons["OK"]
if okBtn.waitForExistence(timeout: 1.5) {
okBtn.tap()
}
Upvotes: 0
Reputation: 565
May not be too helpful, but this matches what I have (for allowing access to Location Services, so I wait for an "Allow" button.) The only difference is that the order I have is 1) let app= 2) add the monitor 3) launch app. All in setup(). The app.tap is in the func testApp(). XCUIApplication() creates a new instance of the app each time it is called: I think I'd try moving that before the monitor in the first instance. Here's my setup method (ignore the UITestHelper call):
override func setUp() {
super.setUp()
continueAfterFailure = false
app = XCUIApplication()
// ensure app is currently authorised. If the first install is to
// happen then the settings won't exist yet but that's ok, the test
// will handle the Location Services prompt and allow.
UITestHelper.resetAuthorisation(setToInUse: true)
addUIInterruptionMonitor(withDescription: "Location Services")
{ (alert) -> Bool in if alert.buttons["Allow"].exists {
alert.buttons["Allow"].tap()
}
return true }
app.launch()
}
and my test:
func testDoesNotAlertReminderIfAuthorised() {
// given
// When
app.tap()
....
Upvotes: 2