'XCUITest ProgressView identifier hardcoded to "In progress" when within a Button

When creating a ProgressView and using .accessibilityIdentifier or a standard label, UI tests are able identify it.

The view:

ProgressView().accessibilityIdentifier("Test")

The following assertion passes:

XCTAssert(app.activityIndicators["Test"].exists)

When placing this ProgressView within a Button however, UI tests fail to identify it.

The view:

Button(action: {}) {
    ProgressView().accessibilityIdentifier("Test")
}

The same assertion fails:

XCTAssert(app.activityIndicators["Test"].exists)

Interestingly, one can use "In progress" to identify the ProgressView within a Button, but what about when I have multiple?

XCTAssert(app.activityIndicators["In progress"].exists)

Why is this ProgressView not identifiable within a Button via it's accessibilityIdentifier?

Bonus question, why is this available under app.activityIndicators but not app.progressIndicators as one might expect?

  • Xcode 13.3.1
  • iOS 15.4


Solution 1:[1]

I would assume that when your ProgressView is placed inside the button it probably becomes of type 'otherElement' and this is the reason you are unable to find it using 'app.activityIndicators'. I would suggest you print out your app elements hierarchy using:

print(app.debugDescription)

or while debugging using the lldb:

po app

and check the actual type of the element and how it fits in the hierarchy. Or you could directly test it out using:

app.otherElements["Test"].exists

Edit: I did not understand the initial problem so I am adding to the answer about your question for multiple existing indicators. In this case you might want to avoid using app.activityIndicators and improve your queries like this:

  1. Using a specific button element to get the needed indicator:
let button = app.buttons["test"]
let indicator = button.activityIndicators.element(boundBy: 0)
  1. Using XCUIElementQuery:
let buttons = app.buttons.matching(identifier: "test")
let indicator = buttons.element(boundBy: 0).activityIndicators.element(boundBy: 0)

With these you don't even have to use the activityIndicator accessibilityIdentifier.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1