4

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?

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116

2 Answers2

6

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.

Oletha
  • 7,324
  • 1
  • 26
  • 46
  • 1
    Thanks for your answer. I tried `shopEasyApp.webViews[0]`, but this gave the error `Expression type 'XCUIElementQuery' is ambiguous without more context.` However, `shopEasyApp.webViews.firstMatch` did work. Maybe you could update your answer, if required. – Reinhard Männer Oct 28 '19 at 10:41
  • My bad, I would actually suggest using `elementBound(by: 0)` rather than `firstMatch`, since `firstMatch` is only meant for using when there is only one result, to speed up parsing. I will update my answer :) – Oletha Oct 29 '19 at 17:11
  • @Oletha is `elementBound(by: 0)` a method in XCTest, because i couldnt find any method of this type – Samarth Kejriwal Dec 04 '19 at 07:34
  • 1
    It is a method on XCUIElementQuery objects – Oletha Dec 04 '19 at 12:36
0

I have faced similar issue - there were no webview's descendants. After investigation it turned out that everything is OK on iOS 13.1 but not on iOS 13.3.

I think it's a simulator's bug.

For all facing the same problem - specify earlier version (13.1) until it's fixed.

serhii.syrotynin
  • 241
  • 1
  • 14