Xcode UI test - UI Testing Failure - Failed to scroll to visible (by AX action) when tap on Search field "Cancel' button
I am trying to dismiss the search field by tapping 'Cancel' button in search bar.
The test case is failing to find the cancel button. It was working fine in Xcode 7.0.1
I have added predicate to wait for button to appear. The test case is failing when we tap of "cancel" button
let button = app.buttons[“Cancel”]
let existsPredicate = NSPredicate(format: "exists == 1")
expectationForPredicate(existsPredicate, evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)
button.tap() // Failing here
logs:
t = 7.21s Tap SearchField
t = 7.21s Wait for app to idle
t = 7.29s Find the SearchField
t = 7.29s Snapshot accessibility hierarchy for com.test.mail
t = 7.49s Find: Descendants matching type SearchField
t = 7.49s Find: Element at index 0
t = 7.49s Wait for app to idle
t = 7.55s Synthesize event
t = 7.84s Wait for app to idle
t = 8.97s Type '[email protected]' into
t = 8.97s Wait for app to idle
t = 9.03s Find the "Search" SearchField
t = 9.03s Snapshot accessibility hierarchy for com.test.mail
t = 9.35s Find: Descendants matching type SearchField
t = 9.35s Find: Element at index 0
t = 9.36s Wait for app to idle
t = 9.42s Synthesize event
t = 10.37s Wait for app to idle
t = 10.44s Check predicate `exists == 1` against object `"Cancel" Button`
t = 10.44s Snapshot accessibility hierarchy for com.test.mail
t = 10.58s Find: Descendants matching type Button
t = 10.58s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.58s Tap "Cancel" Button
t = 10.58s Wait for app to idle
t = 10.64s Find the "Cancel" Button
t = 10.64s Snapshot accessibility hierarchy for com.test.mail
t = 10.78s Find: Descendants matching type Button
t = 10.78s Find: Elements matching predicate '"Cancel" IN identifiers'
t = 10.79s Wait for app to idle
t = 11.08s Synthesize event
t = 11.13s Scroll element to visible
t = 11.14s Assertion Failure: UI Testing Failure - Failed to scroll to visible (by AX action) Button 0x7f7fcaebde40: traits: 8589934593, {{353.0, 26.0}, {53.0, 30.0}}, label: 'Cancel', error: Error -25204 performing AXAction 2003
I guess here "Cancel" button returns false
for hittable
property, that is preventing it from tapping.
If you see tap()
in documentation it says
/*!
* Sends a tap event to a hittable point computed for the element.
*/
- (void)tap;
It seems things are broken with Xcode 7.1. To keep myself (and you too ;)) unblocked from these issues I wrote an extension on XCUIElement
that allows tap on an element even if it is not hittable. Following can help you.
/*Sends a tap event to a hittable/unhittable element.*/
extension XCUIElement {
func forceTapElement() {
if self.hittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
coordinate.tap()
}
}
}
Now you can call as
button.forceTapElement()
Update - For Swift 3 use the following:
extension XCUIElement {
func forceTapElement() {
if self.isHittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx:0.0, dy:0.0))
coordinate.tap()
}
}
}
For me, the root cause was that the objects I wanted to tap
- have been set to hidden (and back)
- have been removed and re-attached
In both cases the isAccessibilityElement
property was false
afterwards. Setting it back to true
fixed it.
This question ranks well for Google queries around the term "Failed to scroll to visible (by AX action) Button". Given the age of the question I was inclined to think this was no longer an issue with the XCUITest framework as the accepted answer suggests.
I found this issue was due to the XCElement
existing, but being hidden behind the software keyboard. The error is emitted by the framework since it is unable to scroll a view that exists into view to be tappable. In my case the button in question was behind the software keyboard sometimes.
I found the iOS Simulator's software keyboard may be toggled off in some cases (eg: on your machine) and toggled on in others (eg: on your CI). In my case I had toggled the software keyboard off on one machine, and by default it was toggled on on others.
Solution: Dismiss the keyboard before attempting to tap buttons that may be behind it.
I found tapping somewhere that explicitly dismissed the keyboard before tapping on the button solved my problem in all environments.
I added add some actions to get the current responder to resignFirstResponder. The views behind my text views will force the first responder to resign, so I tap somewhere just underneath the last text area.
/// The keyboard may be up, dismiss it by tapping just below the password field
let pointBelowPassword = passwordSecureTextField.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1))
pointBelowPassword.press(forDuration: 0.1)
Please check the trait of the element, i was facing the same issue with TableViewSectionHeader, i was trying to tap but it was failing at every point