Cannot assign accessibilityIdentifier to a SwiftUI view

544 Views Asked by At

Setup:

I have a SwiftUI Map with some custom annotationItems. I want to check the numbers of annotationItems on the map in UITests. Thus, I am trying to assign to each annotationItem an accessibilityIdentifier, so that I can query for them. There are 2 MapAnnotation views with a pin image instantiated as:

    Map(coordinateRegion: $region,
            interactionModes: .all,
            showsUserLocation: true,
            annotationItems: annotations) { annotation in
        MapAnnotation(coordinate: annotation.coordinate, anchorPoint: CGPoint(x: 0.5, y: 1)) {
            GeometryReader { geo in
                AnnotationView(annotation: annotation,
                                             region: region, 
                                             mapViewModel: mapViewModel, 
                                             annotationDragged: $annotationDragged)
                .accessibilityIdentifier(kLocationPin)
            }
            .frame(width: 30, height: 30)
        }

Problem:

In my test method, I query for the map annotations. Since map annotations are handled in UITests as otherElements of the app, I am using:

let actualPinsShown = app.otherElements.matching(identifier: kLocationPin)

However, this query does not find any map annotation.
If I issue in the debugger the following command

(lldb) po app.otherElements  

a lot of otherElements are printed, among them

  Other, 0x128d19c80, {{30.3, 273.0}, {30.0, 30.0}}, label: 'Stecknadel'
  Other, 0x128d1c300, {{332.3, 576.0}, {30.0, 30.0}}, label: 'Stecknadel'  

Here, the label Stecknadel (the German word for pin) obviously indicates the 2 MapAnnotation views that display a pin.
However, the accessibilityIdentifier is not set, and thus they cannot be found by the UITest.

Questions:

Why is the accessibilityIdentifier not set?
Is something wrong with my code?
If so, how to do it right? If not, is there a workaround?

PS:
It seems that others have similar problems, see here. I am working with Xcode Version 14.2 (14C18). Maybe this an unfixed bug.

1

There are 1 best solutions below

0
Reinhard Männer On

Problem solved, maybe by a workaround:

My AnnotationView is essentially the following (unimportant code left out):

struct AnnotationView: View {
    var body: some View {
        GeometryReader { geo in
            Image("PinRed")
        }
        .frame(width: 30, height: 30)
    }
}

In the code presented in my question, I tried to set the accessibilityIdentifier for an AnnotationView as

AnnotationView(annotation: annotation,
               region: region, 
               mapViewModel: mapViewModel, 
               annotationDragged: $annotationDragged)
.accessibilityIdentifier(kLocationPin)  

The docs say: accessibilityIdentifier(_:) Uses the string you specify to identify the view.
I therefore assumed that my AnnotationView will get this identifier. But this is not true.

If I query in the debugger for images using app.images.matching(identifier: kLocationPin), I get

↪︎Find: Elements matching predicate '"LocationPin" IN identifiers'
  Output: {
    Image, 0x14725f2c0, {{30.3, 273.0}, {30.0, 30.0}}, identifier: 'LocationPin', label: 'PinRed'
    Image, 0x147260940, {{332.3, 576.0}, {30.0, 30.0}}, identifier: 'LocationPin', label: 'PinRed'
  }

This shows that the accessibilityIdentifier is not attached to the AnnotationView, but to the image inside.
I consider this as a SwiftUI bug, because the identifier identifies not the View it was attached to, but a View inside.