Zhou Haibo
Zhou Haibo

Reputation: 2068

SwiftUI: Custom view is un-hittable in XCTest

During Xcode UI test, I found my custom view's (MenuViewButton) is un-hittable in a test, I could found it but cannot touch it. In debug , when I po isHittable in console, it returns false. However I'm not sure if this is the correct behavior.

Per this thread XCUIElement exists, but is not hittable said, isHittable is default false for custom view element, and default true for UIKit standard view. But I don't know if it is the same behavior in SwiftUI.

Since the way someView.isAccessibilityElement = true is not possible in SwiftUI. My question is how could I let my custom view became hittable? Then it could be tapped in a test.

    private var aView: some View {
        MenuViewButton(
            image: Image("an image name"),
            text: Text("a string")
        )
        .accessibility(identifier: "xxx name")
    }

I also use force tap with coordinate in case tap() is not working, but to give a offset of normalizedOffset didn't fix the problem in all places, it means some un-hittable element could be tapped, that is great but some others still not.

So may I know where normalizedOffset is start, from the middle of frame to give the offset or the top left?

    func forceTapElement(timeout: TimeInterval) {
        if !self.waitForExistence(timeout: timeout) {
            return
        }
        
        if self.isHittable {
            self.tap()
        } else {
            let coordinate: XCUICoordinate = self.coordinate(withNormalizedOffset: CGVector(dx: 0.1, dy: 0.0))
            coordinate.tap()
        }
    }

Upvotes: 1

Views: 1338

Answers (2)

Lukas
Lukas

Reputation: 2535

I have the same situation and am looking for answers. What has worked for me was to use: let coordinate = element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))

Still this seems like workaround for a real problem. One other strange thing is that i do not have this problem on iOS15.0 simulator, only for later versions. Currently trying with iOS15.2

One more thing I've tried is to add .accessibilityElement(children: .combine) and specificly telling it's a button with .accessibility(addTraits: .isButton) But this doesn't solve the problem.

Seems that isAccessibilityElement would be an answer here, but SwiftUI doesn't seem to have such.

Upvotes: 0

Roman Zakharov
Roman Zakharov

Reputation: 2273

  1. Add https://github.com/devexperts/screenobject as a dependency
  2. Use .tapUnhittable() instead of .tap() for this particular view. It gets the coordinates and taps using them

Upvotes: 0

Related Questions