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:
My questions are:
What is wrong with my code, and how to do it correctly?
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.