Xcode 7 UI Testing: how to dismiss a series of system alerts in code
Xcode 7.1
Xcode 7.1 has finally fixed the issue with system alerts. There are, however, two small gotchas.
First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert.
I believe that returning true
from the handler marks it as "complete", which means it won't be called again. For your situation I would try returning false
so the second alert will trigger the handler again.
Xcode 7.0
The following will dismiss a single "system alert" in Xcode 7 Beta 6:
let app = XCUIApplication()
app.launch()
// trigger location permission dialog
app.alerts.element.collectionViews.buttons["Allow"].tap()
Beta 6 introduced a slew of fixes for UI Testing and I believe this was one of them.
Also note that I am calling -element
directly on -alerts
. Calling -element
on an XCUIElementQuery
forces the framework to choose the "one and only" matching element on the screen. This works great for alerts where you can only have one visible at a time. However, if you try this for a label and have two labels the framework will raise an exception.
Dismissing alert XCUITest
I improve the answer of @user3271402
addUIInterruptionMonitorWithDescription("alert description") { (alert) -> Bool in
let alertButton = alert.buttons["OK"]
if alertButton.exists {
alertButton.tap()
return true
}
return false
}
app.tap()
Just tap if the alert exists. If the alert doesn't happen return false and after tap the app and the end.
dismiss location services request dialog
You have to interact with the app right after adding the UIInterruptionMonitor. This can be a simple tap:
addUIInterruptionMonitor(withDescription: "Location Dialog") { (alert) -> Bool in
let button = alert.buttons["Allow"]
if button.exists {
button.tap()
return true
}
return false
}
// interact with the app
app.tap()
If app.tap()
interferes with your test you could also use app.swipeUp()
Be aware that the location service permission dialog changed in iOS11. There are now 3 Buttons, so you have to use alert.buttons["Always Allow"]
to dismiss the dialog.
iOS UITesting : Handle all system prompt automatically with addUIInterruptionMonitorWithDescription
here the xcode-documentation of addUIInterruptionMonitorWithDescription
.
/*! Adds a handler to the current context. Returns a token that can be used to unregister the handler. Handlers are invoked in the reverse order in which they are added until one of the handlers returns true, indicating that it has handled the alert.
@param handlerDescription Explanation of the behavior and purpose of this handler, mainly used for debugging and analysis.
@param handler Handler block for asynchronous UI such as alerts and other dialogs. Handlers should return true if they handled the UI, false if they did not. The handler is passed an XCUIElement representing the top level UI element for the alert.
*/
public func addUIInterruptionMonitorWithDescription(handlerDescription: String, handler: (XCUIElement) -> Bool) -> NSObjectProtocol
1) "Location Dialog" is just a handlerDescription for you to identifie what alert you handle. You can write somethings else.
2) You have to use the same method. Just tap the app after.
Here i use this part of code to handle Push notifications:
addUIInterruptionMonitorWithDescription("Push notifications") { (alert) -> Bool in
if alert.buttons["OK"].exists {
alert.buttons["OK"].tap()
return true
}
return false
}
app.tap()
Cheers
Related Topics
Pulling Data from a Cmsamplebuffer in Order to Create a Deep Copy
Delete Cell from Uicollectionview Without Reloading from Top
How to Resize Uitableviewcell to Fit Its Content
Uinavigationcontroller Interactivepopgesturerecognizer Working Abnormal in iOS7
Multiple Checkmark When Row Selected in Uitableview iOS
How to Tell If Blocks in Loop All Have Completed Executing
iOS 11+ How to Migrate Existing Core Data to Shared App Group for Use in Extension
How to Play Movie with a Url Using a Custom Nsurlprotocol
Installed App from Testflight Crashes Due to Alleged Uisearchdisplaycontroller
Import Framework in Swift Project, Xcode
To Change the Color of Unselected Uitabbar Icon in iOS 7
Using Apple's Reachability Class in Swift
Customizing the Mkannotation Callout Bubble
External Framework File/File.H (Parse/Parse.H) File Not Found
Status Bar Visible on iPad Mini Despite Setting Uiviewcontrollerbasedstatusbarappearance to No