'XCTest How to tap on Url (Link) inside UITextview?

enter image description here

I have added accessibilityIdentifier to the source code. And did:

let privacypolicyurl = app.tables.textViews["privacyPolicy"]
privacypolicyurl.tap()

And another way:

let privacypolicyurl =
    app.tables.textViews.containing(.link,identifier:"privacy Policy").element
privacypolicyurl.tap()

Then tried to debug with po app.links and see this:

Link 0x618000173140: traits: 8589934594, {{261.7, 592.3}, {74.7, 17.5}}, label: 'Privacy Policy' }

So, I came up with

let cooridnate = 
  app.tables.textViews["privacyPolicy"].coordinate(withNormalizedOffset: CGVector(dx: 261.7, dy: 592.3))
cooridnate.tap()

Unfortunately none of these worked out for me. Please help to figure out.



Solution 1:[1]

From the looks of your debug output, you'll be fine without specifying which views the link is contained within - it's possible that the link isn't inside the views that you think it is inside. It should be fine to just do:

app.links["Privacy Policy"].tap()

I see your thinking with the coordinate, but you would want to get a coordinate object for the element first and then use the withOffset method on XCUICoordinate, since that takes a vector with absolute values. coordinateWithNormalizedOffset takes a vector with relative values, so in your example, you would be trying to tap the point that is 261 times the width of the element, to the right of the element's origin.

Solution 2:[2]

Links within UITextViews have the following strange behaviour:

  • link.tap() provides an error during "Synthesize event"
  • link.coordinate() returns zero values
  • link.accessibilityFrame() returns zero values

But we can use the frame of the link element to access the link. You can use the following extension:

import XCTest

extension XCUIElement {

  public func tapFrameCenter() {
      let frameCenterCoordinate = self.frameCenter()
      frameCenterCoordinate.tap()
  }

  func frameCenter() -> XCUICoordinate {
      let centerX = self.frame.midX
      let centerY = self.frame.midY

      let normalizedCoordinate = XCUIApplication().coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
      let frameCenterCoordinate = normalizedCoordinate.withOffset(CGVector(dx: centerX, dy: centerY))

      return frameCenterCoordinate
  }
}

Solution 3:[3]

You should access the link directly from the textView

let textView = app.textViews["privacyPolicyTextView"]
textView.links["Privacy Policy"].tap()

Solution 4:[4]

The problem here is tapping on links(attributed string) will not take effect unless you give textView an accessibility identifier.

First, this would not work.

app.links["your attributed string"].tap().

To make it work, give an accessibility identifier to your textview.

textview.accessibilityIdentifier = "my_textview"

After that, try to access it with below lines.

app.textViews["my_textview"].links.firstMatch.tap() or app.textViews["my_textview"].links.matching(identifier: "your attributed string").tap()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Oletha
Solution 2 Linda
Solution 3 Nikita
Solution 4 ChuckZHB