Подтвердить что ты не робот

Как скрыть клавиатуру в приложении Swift во время тестирования пользовательского интерфейса

Я только начал тестирование пользовательского интерфейса в XCode 7 и столкнулся с этой проблемой:

Мне нужно ввести текст в текстовое поле и затем нажать кнопку. К сожалению, эта кнопка скрыта за клавиатурой, которая появилась при вводе текста в текстовое поле. XCode пытается прокрутить, чтобы сделать его видимым, но мой вид не прокручивается, поэтому он терпит неудачу.

Мое текущее решение таково:

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

Я могу сделать это, потому что мой ViewController перехватывает прикосновения:

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

Я не очень доволен своим решением, есть ли другой способ, как скрыть клавиатуру во время тестирования пользовательского интерфейса?

4b9b3361

Ответ 1

Если вы настроили свои текстовые поля, чтобы отменить FirstResponder (через textField.resignFirstResponder() или self.view.endEditing(true)) в методе делегата textFieldShouldReturn(), тогда

textField.typeText("\n")

сделает это.

Ответ 2

Основываясь на вопросе к блогу Джо, у меня есть проблема, из-за которой после нескольких запусков на симуляторе клавиатурам не удается спрятаться, используя этот фрагмент кода:

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

Итак, я изменил это: (спасибо Джо)

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

Здесь я пытаюсь определить, остается ли клавиатура открытой после нажатия кнопки "скрыть", если она включена, я набираю "\n", что в моем случае тоже закрывает клавиатуру.

Это также бывает сложно, потому что иногда симулятор теряет фокус ввода с клавиатуры, и это может привести к неудаче теста, но по моему опыту частота неудач ниже, чем у других подходов, которые я использовал.

Я надеюсь, что это может помочь.

Ответ 3

Я всегда использую это, чтобы программно скрыть клавиатуру в Swift UITesting:

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

Ответ 4

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

Ответ 5

Ответ на ваш вопрос лежит не в вашем тестовом коде, а в коде приложения. Если пользователь не может вводить текст с помощью экранной программной клавиатуры, а затем нажмите на кнопку, вы должны либо отменить тест, отпустив клавиатуру (как пользователь должен был бы нажать, чтобы нажать на кнопку), либо сделать прокручиваемое представление.

Ответ 6

Просто убедитесь, что клавиатура выключена в симуляторе перед запуском тестов.

Hardware- > Keyboard- > Connect Hardware Keyboard.

Затем введите свой текст, используя панель палитры

textField.tap()
UIPasteboard.generalPasteboard().string = "Some text"
textField.doubleTap()
app.menuItems["paste"].tap()

Ответ 7

С Swift 4.2 вы можете сделать это сейчас с помощью следующего фрагмента:

let app = XCUIApplication()
if app.keys.element(boundBy: 0).exists {
    app.typeText("\n")
}

Ответ 8

Swift 5 вспомогательная функция

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()
        }
    }
}

Ответ 9

Я предпочитаю искать несколько элементов, которые, возможно, видны для нажатия, или продолжения, или как вы хотите это назвать. И выберите правильный.

class ElementTapHelper {

    ///Possible elements to search for.
    var elements:[XCUIElement] = []

    ///Possible keyboard element.
    var keyboardElement:XCUIElement?

    init(elements:[XCUIElement], keyboardElement:XCUIElement? = nil) {
        self.elements = elements
        self.keyboardElement = keyboardElement
    }

    func tap() {
        let keyboard = XCUIApplication().keyboards.firstMatch
        if let key = keyboardElement, keyboard.exists  {
            let frame = keyboard.frame
            if frame != CGRect.zero {
                key.forceTap()
                return
            }
        }
        for el in elements {
            if el.exists && el.isHittable {
                el.forceTap()
                return
            }
        }
    }

}

extension XCUIElement {
    ///If the element isn't hittable, try and use coordinate instead.
    func forceTap() {
        if self.isHittable {
            self.tap()
            return
        }
        //if element isn't reporting hittable, grab it coordinate and tap it.
        coordinate(withNormalizedOffset: CGVector(dx:0, dy:0)).tap()
    }
}

У меня это хорошо работает. Вот как я бы обычно это использовал:

let next1 = XCUIApplication().buttons["Next"]
let keyboardNext = XCUIApplication().keyboards.firstMatch.buttons["Next"]
ElementTapHelper(elements: [next1], keyboardElement: keyboardNext).tap()

Приятно то, что вы можете предоставить несколько элементов, к которым можно прикоснуться, и сначала выполняется поиск элемента клавиатуры.

Еще одним преимуществом этого является то, что при тестировании на реальных устройствах клавиатура открывается по умолчанию. Так почему бы просто не нажать кнопку клавиатуры?

Я использую этот помощник только тогда, когда несколько кнопок выполняют одно и то же действие, а некоторые могут быть скрыты и т.д.