How to hide keyboard in Swift app during UI testing

21,305

Solution 1

If you have set up your text fields to resign FirstResponder (either via textField.resignFirstResponder() or self.view.endEditing(true)) in the textFieldShouldReturn() delegate method, then

textField.typeText("\n")

will do it.

Solution 2

Swift 5 helper function

func dismissKeyboardIfPresent() {
    if app.keyboards.element(boundBy: 0).exists {
        if UIDevice.current.userInterfaceIdiom == .pad {
            app.keyboards.buttons["Hide keyboard"].tap()
        } else {
            app.toolbars.buttons["Done"].tap()
        }
    }
}

Solution 3

Based on a question to Joe's blog, I have an issue in which after a few runs on simulator the keyboards fails to hide using this piece of code:

XCUIApplication().keyboard.buttons["Hide keyboard"]

So, I changed it to: (thanks Joe)

XCUIApplication().keyboard.buttons["Hide keyboard"]
let firstKey = XCUIApplication().keys.elementBoundByIndex(0)
if firstKey.exists {
   app.typeText("\n")
}

What I try to do here is detecting if the keyboard stills open after tap the hide button, if it is up, I type a "\n", which in my case closes the keyboard too.

This also happens to be tricky, because sometimes the simulator lost the focus of the keyboard typing and this might make the test fail, but in my experience the failure rate is lower than the other approaches I've taken.

I hope this can help.

Solution 4

XCUIApplication().toolbars.buttons["Done"].tap()

Solution 5

I always use this to programmatically hide the keyboard in Swift UITesting:

XCUIApplication().keyboards.buttons["Hide keyboard"].tap()
Share:
21,305

Related videos on Youtube

leizeQ
Author by

leizeQ

Updated on July 09, 2022

Comments

  • leizeQ
    leizeQ almost 2 years

    I just started with UI testing in Xcode 7 and hit this problem:

    I need to enter text into a textfield and then click a button. Unfortunately this button is hidden behind the keyboard which appeared while entering text into the textfield. Xcode is trying to scroll to make it visible but my view isn't scrollable so it fails.

    My current solution is this:

    let textField = app.textFields["placeholder"]
    textField.tap()
    textField.typeText("my text")
    app.childrenMatchingType(.Window).elementBoundByIndex(0).tap() // hide keyboard
    app.buttons["hidden button"].tap()
    

    I can do this because my ViewController is intercepting touches:

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        view.endEditing(false)
        super.touchesBegan(touches, withEvent: event)
    }
    

    I am not really happy about my solution, is there any other way how to hide the keyboard during UI testing?

    • Tj3n
      Tj3n over 8 years
      If u have issue with keyboard hides button, u can just push the whole view up with setContentOffset till the button is visible, it doesnt matter if your view is scrollable or not
    • michal.ciurus
      michal.ciurus over 8 years
      1. If you can't access a button when the keyboard is visible, isn't that a UX problem ? 2. These are just tests. Tests are expected to have hacky code so I don't see what's your problem here :) Just leave it, if it works.
  • Rayfleck
    Rayfleck almost 8 years
    "make the test dismiss the keyboard" - Do you have any suggestions as to how to accomplish this? XCUIElement has no such notion as resignFirstResponder.
  • Rayfleck
    Rayfleck almost 8 years
    app.keyboards.buttons["Hide keyboard"].tap()
  • Mark Bridges
    Mark Bridges about 7 years
    Doesn't work for me on iPhone. Could this be iPad only?
  • Sujananth
    Sujananth about 6 years
    Value of type 'XCUIApplication' has no member 'keyboard'. @charlieSeligman Does the code works in the device or code works only for simulator?
  • Sujananth
    Sujananth about 6 years
    Working fine in all cases
  • caffeinum
    caffeinum about 6 years
    I believe you can tap away from keyboard to hide it. Something like app.tap() or app.swipeDown() should do it.
  • Degard
    Degard about 6 years
    It works but in some cases I have error: Assertion Failure: <unknown>:0: failed: Timed out after waiting 1.0s for KeyEventCompleted after sending event for '
  • Vladimír Slavík
    Vladimír Slavík about 6 years
    Does not work for all simulators. My tests work for iPhone 6 and 7 but not on iPhoneX.
  • Sean Long
    Sean Long over 5 years
    Also doesn't work if the keyboard doesn't have a "Done", ie a numpad.
  • Gabriel Pita
    Gabriel Pita about 5 years
    using this app github.com/Shashikant86/XCUITest-TAU I can't hide the keyboard in any way, not with \n nor with ["hide keyboard"]. very weird
  • Nisim Naim
    Nisim Naim almost 5 years
    I simply added "\n" in the end of the string i'm sending to the textField and it worked like magic. Thank you.
  • logankilpatrick
    logankilpatrick almost 5 years
    Same for me @JosePita
  • Ramy Al Zuhouri
    Ramy Al Zuhouri over 4 years
    This is only for the iPad. On the iPhone you can press the "done" button if the keyboard has it (it depends on the UI element), or if it doesn't have it, then the only way is to click somewhere else (e.g. on a label).
  • JBarros35
    JBarros35 over 3 years
    Failed to get matching snapshot: No matches found for Descendants matching type Toolbar from input {(