Billy Boyo
Billy Boyo

Reputation: 889

XCUITest - neither element nor descendant has keyboard focus

I am testing adding a comment to my app, on my other UI tests I have used the typeText function and everything works perfectly fine. I have also clicked to make Connect hardware keyboard' is off. The app terminates testing and shows the error UI Testing Failure - Neither element nor any descendant has keyboard focus during the addComment method. Any ideas?

  func testAddComment() {
    let featuredPage = self.app.tabBars["Featured"]
    if featuredPage.exists {
        featuredPage.tap()
    }
    sleep(2)
    let featuredOffer = self.app.tables.cells.elementBoundByIndex(1)
    if featuredOffer.exists {
        featuredOffer.tap()
    }
    sleep(2)
    let addComment = self.app.staticTexts["Add a comment"]
    if addComment.exists {
        addComment.tap()
        addComment.typeText("Test comment")
    }
    sleep(2)
    let postComment = self.app.buttons["Send"]
    if postComment.exists {
        postComment.tap()
    }
    sleep(2)
}

Upvotes: 6

Views: 8069

Answers (5)

alekop
alekop

Reputation: 3016

Turn off I/O -> Keyboard -> Connect Hardware Keyboard in the Simulator menu.

When this option is on, the Simulator doesn't bring up the soft keyboard, so the OS (sometimes) thinks the text field is not focused. Most of my tests have no problem typing in text fields with this option on, but some fail, especially search bars.

Upvotes: -1

abhidby
abhidby

Reputation: 1

You can try solving this issue by using .doubletap() before you & enter the value in .typeText(string) it worked for me.

let addComment = self.app.staticTexts["Add a comment"]
    if addComment.exists {
        addComment.doubleTap()
        addComment.typeText("Test comment")

Upvotes: 0

Duncan Babbage
Duncan Babbage

Reputation: 20177

Likely cause:
An extremely common cause of this symptom is to have enabled a parent view of the field in question as an accessibility element. Ensure that none of the parents of the field are enabled as accessibility elements, and the problem is likely to be resolved.

Explanation
This error message can be particularly confusing when you can see that a previous step in the XCUITest has correctly activated a text field or similar as the first responder, the keyboard has appeared, and functionally the field has keyboard focus.

Essentially, the error message is slightly misleading as the tendency is to focus on the keyboard focus part and think that it is telling you that nothing has keyboard focus. Instead, what the message is telling you is that none of the accessibility elements that XCUITest can access have the keyboard focus. And so it can't direct text to the field in question.

Accessibility elements cannot have children that are also accessibility elements. Therefore, if you place a number of fields inside a view, but then mark that parent view as being an accessibility element, all of the field as its subviews become invisible to the accessibility frameworks. You can see and verify this is what is happening using the Accessibility Inspector app on the Mac alongside the simulator: the fields you are trying to target will not be selectable, and instead there will be a parent view that is.

Upvotes: 9

Billy Boyo
Billy Boyo

Reputation: 889

I found the way around this best was to use menuItem and to paste what I wanted to the textField . This was a strange problem as both textField and staticText both didn't allow the test to run functionally. This is an issue I have reported to apple.

Here is my fix

    let addComment = self.app.staticTexts["Add a comment"]
    if addComment.exists {
        addComment.tap()
        UIPasteboard.generalPasteboard().string = "Test Comment"
        let commentTextField = self.app.staticTexts["Add a comment"]
        commentTextField.pressForDuration(1.1)
        sleep(1)
        app.menuItems.elementBoundByIndex(2).tap()
    }

Upvotes: 5

Oletha
Oletha

Reputation: 7639

You can only use .typeText() on an input element. Static texts are not input elements - they're just text. Your addComment constant is probably the placeholder text within your text field. Tapping on the placeholder text probably activates the text field and keyboard, but you cannot call .typeText() on the placeholder text as the text field is its parent, not its descendant.

You need to call .typeText() on your text field, which should have focus after you tap in it.

let addComment = self.app.textFields["addCommentIdentifier"]
if addComment.exists {
    addComment.tap()
    addComment.typeText("Test comment")
}

Upvotes: 1

Related Questions