How to type into a UITextView inside a XCTestCase
Asked Answered
A

2

6

How do you type into a UITextView inside a XCTestCase? The UITextView is the first responder so it already had focus and the keyboard is up.

I've tried:

app.typeText("footer")
app.textViews.element(boundBy: 0).typeText("foobar")
app.links.element(boundBy: 0).typeText("foobar")

for some reason app.textViews.count always returns 0?

Alkaloid answered 2/6, 2017 at 18:20 Comment(2)
Is your text view inside a container view? What's the view hierarchy like?Karisakarissa
@Oletha, it's inside a stack. The stack is the top most view.Alkaloid
K
7

The problem is not that .typeText(_:) doesn't work, it's that your query doesn't resolve to an element.

It can sometimes seem like the query is not working properly when the view you're trying to find is inside an accessible container view of some sort. You can mitigate this by explicitly disabling accessibility in the container view.

Set the stack view that contains the text view to not be an accessibility element and then set an accessibility identifier on the text view.

// app code
let stack: UIStackView!
let textView: UITextView!
stack.isAccessibilityElement = false
textView.isAccessibilityElement = true
textView.accessibilityIdentifier = "myTextView"

// test code
let app = XCUIApplication()
let textView = app.textViews["myTextView"]
textView.typeText("something")
Karisakarissa answered 5/6, 2017 at 19:44 Comment(5)
Given that UIStackView doesn't display any info or support user interaction per se, why Apple would make it an accessible element by default? If this is indeed the case, wouldn't this result in all sorts of accessibility issues, way beyond UI tests, given how useful/popular UIStackView is?Melan
Accessibility for end users works slightly differently to accessibility for XCTest. I've had quite niche examples where views inside tables are inaccessible to tests but not to Voiceover...Karisakarissa
Ok, wasn't aware of that discrepancy... anyway, the UITableView container, as opposed to UIStackView, supports user interactions (scrolling, etc) so this wouldn't surprise me as much ;)Melan
Coming back to this recently, this doesn't work for me. I continue to be able to resolve the query into an element.Alkaloid
Just because the query returns an XCUIElement object, doesn't meant that that element will be found to exist at runtime. The query may or may not resolve to a single XCUIElement at runtime and cause errors.Karisakarissa
M
4

Try setting an unique accessibility identifier for your UITextView and then:

let textView = app.textViews["uniqueId"]
XCTAssert(textView.exists, "uniqueId text view NOT FOUND")
textView.tap()
textView.typeText("foobar")
Melan answered 2/6, 2017 at 18:49 Comment(5)
This also does not work. Do you have this working in your own code?Alkaloid
What's more this returns 0: app.children(matching: .textView).countAlkaloid
@Alkaloid Works great for UITextField, so I can't see why it won't work for UITextView as well. I added an extra assert just to be safe...Melan
...you could try to record the UI test instead to see if Xcode can find your text view for you ;) (This is done by the red button on the bottom.)Melan
Try it and let me know how it goes. I find that the code that the recorder gives code that doesn't behave correctly. I know how to do it for the UITextField, if the UITextView behaved like the UITextField I wouldn't have a problem.Alkaloid

© 2022 - 2024 — McMap. All rights reserved.