Search code examples
ios13xcode-ui-testingxcode11

iOS 13 Xcode UI test Automation type mismatch


My app uses a WKWebView that is setup in code (this is done because of this bug in iOS 10):

final class HelpViewController: UIViewController {
  // …
    var webView: WKWebView! 

  override func viewDidLoad() {
    super.viewDidLoad()

        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(webView)
        let margins = view.layoutMarginsGuide
        webView.topAnchor.constraint(equalTo: self.back.bottomAnchor).isActive = true
        webView.rightAnchor.constraint(equalTo: margins.rightAnchor).isActive = true
        webView.leftAnchor.constraint(equalTo: margins.leftAnchor).isActive = true
        webView.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
        webView.navigationDelegate = self
  //…
}  

My UI test looks like this:

func test_helpButtonShowsHelpText() {
  //…
    let webView = shopEasyApp.webViews.element
    let webViewExists = webView.waitForExistence(timeout: kDefaultUITestTimeout)
    XCTAssert(webViewExists, "Web view does not exist")
    let webViewIsHittable = webView.isHittable  
  //…  
  }  

This test run without problems up to iOS 12.

With iOS 13, it stops at the test webView.isHittable with the following error:

Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x600000bdfbb0>.  

The log says:

Assertion Failure: ShopEasyBasicUITests.swift:1100: Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x600003efb4d0>.
Sparse tree of matches:
→Application, pid: 71038, label: 'Shop Easy!'
  ↳Window, {{0.0, 0.0}, {375.0, 812.0}}
    ↳Other, {{0.0, 0.0}, {375.0, 812.0}}
      ↳Other, {{0.0, 0.0}, {375.0, 812.0}}
        ↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
          ↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
            ↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
Possibly caused by runtime issues:
Automation type mismatch: computed WebView from legacy attributes vs ScrollView from modern attribute. Input attributes and values: {
    "XC_kAXXCAttributeAutomationType" = 46;
    "XC_kAXXCAttributeElementBaseType" = UIScrollView;
    "XC_kAXXCAttributeElementType" = WKScrollView;
    "XC_kAXXCAttributeTraits" = 8589934592;
}
Automation type mismatch: computed Other from legacy attributes vs WebView from modern attribute. Input attributes and values: {
    "XC_kAXXCAttributeAutomationType" = 58;
    "XC_kAXXCAttributeElementBaseType" = UIView;
    "XC_kAXXCAttributeElementType" = WKWebView;
    "XC_kAXXCAttributeTraits" = 146028888064;
}
Automation type mismatch: computed Other from legacy attributes vs WebView from modern attribute. Input attributes and values: {
    "XC_kAXXCAttributeAutomationType" = 58;
    "XC_kAXXCAttributeElementBaseType" = UIView;
    "XC_kAXXCAttributeElementType" = WKContentView;
    "XC_kAXXCAttributeTraits" = 146028888064;
}  

The view hierarchy is the following:
enter image description here

My questions are:
What is wrong with my code, and how to do it correctly?


Solution

  • You have three WebKit views in play which XCTest can see:

    • WKScrollView
    • WKWebView
    • WKContentView

    It looks like they have changed the way that elements are given their type on iOS 13, meaning that your view hierarchy now contains multiple elements which resolve to being classed as a WebView. It appears that WKWebView and WKContentView now both resolve to being elements of type WebView, whereas in iOS 12, only the WKScrollView (which, in iOS 13, no longer resolves to being classed as a WebView element) was classed as a WebView.

    Now for the query:

    shopEasyApp.webViews.element
    

    The query uses element, which is only supposed to be used when you know the query will resolve to a single element. Since there are now 2 results for shopEasyApp.webViews, there is not a single element for element to return. You are able to check for existence because checking XCUIElement's exists property does not require the query to be resolved successfully. However, all other XCUIElement properties do require the query to be resolved, so when isHittable is used, the XCTest engine attempts to resolve the query, finds that the query does not resolve to a single element as expected, and throws this error.

    Multiple matching elements found for <XCUIElementQuery: 0x600003efb4d0>
    

    To resolve this, I suggest you modify the query to use the first matching index instead of using element:

    shopEasyApp.webViews.elementBound(by: 0)
    

    In the event that there is more than a single WebView element on screen, this query will choose the first element in the list.