Ответ 1
Если вы настроили свои текстовые поля, чтобы отменить FirstResponder (через textField.resignFirstResponder()
или self.view.endEditing(true)
) в методе делегата textFieldShouldReturn()
, тогда
textField.typeText("\n")
сделает это.
Я только начал тестирование пользовательского интерфейса в 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)
}
Я не очень доволен своим решением, есть ли другой способ, как скрыть клавиатуру во время тестирования пользовательского интерфейса?
Если вы настроили свои текстовые поля, чтобы отменить FirstResponder (через textField.resignFirstResponder()
или self.view.endEditing(true)
) в методе делегата textFieldShouldReturn()
, тогда
textField.typeText("\n")
сделает это.
Основываясь на вопросе к блогу Джо, у меня есть проблема, из-за которой после нескольких запусков на симуляторе клавиатурам не удается спрятаться, используя этот фрагмент кода:
XCUIApplication().keyboard.buttons["Hide keyboard"]
Итак, я изменил это: (спасибо Джо)
XCUIApplication().keyboard.buttons["Hide keyboard"]
let firstKey = XCUIApplication().keys.elementBoundByIndex(0)
if firstKey.exists {
app.typeText("\n")
}
Здесь я пытаюсь определить, остается ли клавиатура открытой после нажатия кнопки "скрыть", если она включена, я набираю "\n", что в моем случае тоже закрывает клавиатуру.
Это также бывает сложно, потому что иногда симулятор теряет фокус ввода с клавиатуры, и это может привести к неудаче теста, но по моему опыту частота неудач ниже, чем у других подходов, которые я использовал.
Я надеюсь, что это может помочь.
Я всегда использую это, чтобы программно скрыть клавиатуру в Swift UITesting:
XCUIApplication().keyboards.buttons["Hide keyboard"].tap()
XCUIApplication().toolbars.buttons["Done"].tap()
Ответ на ваш вопрос лежит не в вашем тестовом коде, а в коде приложения. Если пользователь не может вводить текст с помощью экранной программной клавиатуры, а затем нажмите на кнопку, вы должны либо отменить тест, отпустив клавиатуру (как пользователь должен был бы нажать, чтобы нажать на кнопку), либо сделать прокручиваемое представление.
Просто убедитесь, что клавиатура выключена в симуляторе перед запуском тестов.
Hardware- > Keyboard- > Connect Hardware Keyboard.
Затем введите свой текст, используя панель палитры
textField.tap()
UIPasteboard.generalPasteboard().string = "Some text"
textField.doubleTap()
app.menuItems["paste"].tap()
С Swift 4.2 вы можете сделать это сейчас с помощью следующего фрагмента:
let app = XCUIApplication()
if app.keys.element(boundBy: 0).exists {
app.typeText("\n")
}
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()
}
}
}
Я предпочитаю искать несколько элементов, которые, возможно, видны для нажатия, или продолжения, или как вы хотите это назвать. И выберите правильный.
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()
Приятно то, что вы можете предоставить несколько элементов, к которым можно прикоснуться, и сначала выполняется поиск элемента клавиатуры.
Еще одним преимуществом этого является то, что при тестировании на реальных устройствах клавиатура открывается по умолчанию. Так почему бы просто не нажать кнопку клавиатуры?
Я использую этот помощник только тогда, когда несколько кнопок выполняют одно и то же действие, а некоторые могут быть скрыты и т.д.