nalexn / ViewInspector

Runtime introspection and unit testing of SwiftUI views
MIT License
2.09k stars 145 forks source link

Only able to find the first AccessibilityIdentifier applied to a View, unless applied using a ViewModifier. #301

Closed JOyo246 closed 2 weeks ago

JOyo246 commented 2 months ago
struct MyCustomIdentifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .accessibilityIdentifier("Identifier-InModifier")
    }
}
extension MyViewTestCase {

    func testAccessibilityIdentifiers() throws {
        let v = Text("")
            .accessibilityIdentifier("Identifier-BeforeModifier")
            .modifier(MyCustomIdentifier())
            .accessibilityIdentifier("Identifier-AfterModifier")

        print("---- BEGIN ID Dump ----")
        try v.inspect().printOutAllAccessibilityIdentifiers()
        print("---- END ID Dump ----")
    }
}
extension InspectableView {

    func printOutAllAccessibilityIdentifiers() {
        try? find {
            print(try $0.accessibilityIdentifier())
            return false
        }
    }

}

Output here is:

---- BEGIN ID Dump ----
Identifier-BeforeModifier
Identifier-InModifier
---- END ID Dump ----

My Expected Output would be:

---- BEGIN ID Dump ----
Identifier-BeforeModifier
Identifier-InModifier
Identifier-AfterModifier
---- END ID Dump ----
nalexn commented 2 weeks ago

For some modifiers, which could be applied multiple times in the code, like background, inspection function also takes an index, so for introspecting the second one you'd write try sut.inspect().background(1).

The API for accessibilityIdentifier does not take an index, meaning it only looks up for the first instance. I could amend it to consume the index, but I don't see a point - you're meant to apply only a single accessibilityIdentifier per view.

From the docs:

An identifier can be used to uniquely identify an element in the scripts you write using the UI Automation interfaces. Using an identifier allows you to avoid inappropriately setting or accessing an element’s accessibility label.

Technically this is a limitation of the library API here, but there is no practical use to "fixing" it. Let me know if I'm missing anything.