ios - Error de prueba de IU: ni el elemento ni ningún descendiente tienen el foco del teclado en secureTextField
xcode swift (19)
El problema para mí era el mismo que para Ted. En realidad, si se toca el campo de contraseña después del campo de inicio de sesión y el KB de hardware está activado, el teclado del software se descartará en el segundo toque de campo, y no es específico para las pruebas de IU.
Después de algún tiempo jugando con AppleScript, esto es lo que se me ocurrió (las mejoras son bienvenidas):
tell application "Simulator" activate tell application "System Events" try tell process "Simulator" tell menu bar 1 tell menu bar item "Hardware" tell menu "Hardware" tell menu item "Keyboard" tell menu "Keyboard" set menuItem to menu item "Connect Hardware Keyboard" tell menu item "Connect Hardware Keyboard" set checkboxStatus to value of attribute "AXMenuItemMarkChar" of menuItem if checkboxStatus is equal to "✓" then click end if end tell end tell end tell end tell end tell end tell end tell on error tell application "System Preferences" activate set securityPane to pane id "com.apple.preference.security" tell securityPane to reveal anchor "Privacy_Accessibility" display dialog "Xcode needs Universal access to disable hardware keyboard during tests(otherwise tests may fail because of focus issues)" end tell end try end tell end tell
Cree un archivo de secuencia de comandos con el código anterior y agréguelo a los objetivos necesarios (probablemente el objetivo de prueba de IU solo, puede agregar secuencias de comandos similares a sus objetivos de desarrollo para volver a habilitar el teclado HW durante el desarrollo).
Debe agregar la fase
Run Script
en las fases de compilación y usarla de esta manera:
osascript Path/To/Script/script_name.applescript
Este es mi caso:
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("wrong_password") //here is an error
Error de prueba de IU: ni el elemento ni ningún descendiente tienen el foco del teclado. Elemento:
¿Qué está mal?
Esto funciona bien para
textFields
normales, pero el problema surge solo con
secureTextFields
.
¿Alguna solución?
En ocasiones, los campos de texto no se implementan como campos de texto, o se envuelven en otro elemento de la IU y no son fácilmente accesibles. Aquí hay una solución:
//XCUIApplication().scrollViews.otherElements.staticTexts["Email"] the locator for the element
RegistrationScreenStep1of2.emailTextField.tap()
let keys = app.keys
keys["p"].tap() //type the keys that you need
//If you stored your data somewhere and need to access that string //you can cats your string to an array and then pass the index //number to key[]
let newUserEmail = Array(newPatient.email())
let password = Array(newPatient.password)
//When you cast your string to an array the elements of the array //are Character so you would need to cast them into string otherwise //Xcode will compain.
let keys = app.keys
keys[String(newUserEmail[0])].tap()
keys[String(newUserEmail[1])].tap()
keys[String(newUserEmail[2])].tap()
keys[String(newUserEmail[3])].tap()
keys[String(newUserEmail[4])].tap()
keys[String(newUserEmail[5])].tap()
Encontramos el mismo error al configurar el valor de
accessibilityIdentifier
para una vista personalizada (subclase
UIStackView
) que contiene
UIControl
UIControl.
En ese caso, XCTest no pudo obtener el foco del teclado para los elementos descendientes.
Nuestra solución fue simplemente eliminar el
accessibilityIdentifier
de nuestra vista principal y establecer el
accessibilityIdentifier
para las subvistas a través de propiedades dedicadas.
Este problema me causó un mundo de dolor, pero he logrado encontrar una solución adecuada. En el simulador, asegúrese de que ''Hardware -> Teclado -> Conectar teclado de hardware'' esté apagado.
Esto quizás ayude: acabo de agregar una acción de "toque" antes del error; eso es todo :)
func pasteTextFieldText(app:XCUIApplication, element:XCUIElement, value:String, clearText:Bool) {
// Get the password into the pasteboard buffer
UIPasteboard.generalPasteboard().string = value
// Bring up the popup menu on the password field
element.tap()
if clearText {
element.buttons["Clear text"].tap()
}
element.doubleTap()
// Tap the Paste button to input the password
app.menuItems["Paste"].tap()
}
He escrito una pequeña extensión (Swift) que funciona perfectamente para mí. Aquí está el código:
extension XCTestCase {
func tapElementAndWaitForKeyboardToAppear(element: XCUIElement) {
let keyboard = XCUIApplication().keyboards.element
while (true) {
element.tap()
if keyboard.exists {
break;
}
NSRunLoop.currentRunLoop().runUntilDate(NSDate(timeIntervalSinceNow: 0.5))
}
}
}
La idea principal es seguir tocando un elemento (campo de texto) antes de presentar el teclado.
Lo que solucionó este problema para mí fue agregar un sueño de 1 segundo:
let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)
No se equivoque, el problema se debe a que la razón es que ha registrado su tiempo de prueba, su aplicación conectará el teclado de hardware mientras que su simulador de tiempo de prueba automático solo toma el teclado del software. Entonces, ¿cómo solucionar este problema? Simplemente use el teclado de software en su tiempo de grabación. Puedes ver la magia.
Otra causa de este error es si hay una vista principal del campo de texto en el que está intentando ingresar texto que se establece como un elemento de accesibilidad (
view.isAccessibilityElement = true
).
En este caso, XCTest no puede obtener un identificador en la subvista para ingresar el texto y devuelve el error.
Error de prueba de IU: ni el elemento ni ningún descendiente tienen el foco del teclado.
No es que ningún elemento tenga foco (como a menudo puede ver el teclado hacia arriba y el cursor parpadeante en el UITextField), es simplemente que ningún elemento
que pueda alcanzar
tiene foco.
Me encontré con esto cuando intentaba ingresar texto en una UISearchBar.
La barra de búsqueda en sí no es el campo de texto, cuando se configura como un elemento de accesibilidad, se bloquea el acceso al UITextField subyacente.
Para resolver esto,
searchBar.accessibilityIdentifier = "My Identifier"
se configuró en
UISearchBar
sin embargo,
isAccessibilityElement
no se estableció en
true
.
Después de esto, pruebe el código del formulario:
app.otherElements["My Identifier"].tap()
app.otherElements["My Identifier"].typeText("sample text")
Trabajos
Otra respuesta, pero para nosotros el problema era que la vista estaba demasiado cerca de otra vista que tenía un reconocimiento de gestos. Descubrimos que necesitábamos que la vista estuviera al menos a 20 píxeles de distancia (en nuestro caso a continuación). Literalmente 15 no funcionaron y 20 o más lo hicieron. Esto es extraño, lo admito, pero teníamos algunos UITextViews que funcionaban y otros que no, y todos estaban bajo el mismo padre e idéntico otro posicionamiento (y nombres de variables, por supuesto). El teclado encendido o apagado o lo que sea no hizo ninguna diferencia. La accesibilidad mostró los campos. Reiniciamos nuestras computadoras. Hicimos construcciones limpias. Nuevas fuentes de pago.
Recientemente encontramos un truco para hacer que la solución de la respuesta aceptada sea persistente. Para deshabilitar la configuración del simulador: ''Hardware -> Teclado -> Conectar teclado de hardware'' desde la línea de comando uno debe escribir:
defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0
No afectará a un simulador que se esté ejecutando: debe reiniciar el simulador o iniciar uno nuevo para que esa configuración tenga efecto.
Stanislav tiene la idea correcta.
En un entorno de equipo, necesita algo que funcione automáticamente. He encontrado una solución here en mi blog.
Básicamente solo pegas:
UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()
Su primera línea es solo una
definición de consulta
, lo que no significa que
passwordSecureTextField
exista realmente.
Su segunda línea ejecutará dinámicamente la consulta e intentará (re) vincular la consulta al elemento de la interfaz de usuario. Debe ponerle un punto de interrupción y verificar que se encuentre un solo elemento. O simplemente use una afirmación:
XCTAssertFalse(passwordSecureTextField.exists);
De lo contrario, se ve bien,
tap
debería forzar el teclado visible y luego
typeText
debería funcionar.
El registro de errores debería decirle más información.
Tuve el mismo problema con Securetextfields. La opción de conexión de hardware en mi simulador era de, pero todavía se encontró con el problema. Finalmente, esto funcionó para mí (Swift 3):
let enterPasswordSecureTextField = app.secureTextFields["Enter Password"]
enterPasswordSecureTextField.tap()
enterPasswordSecureTextField.typeText("12345678")
Use una suspensión entre iniciar la aplicación y escribir datos en campos de texto como este:
sleep(2)
En mi caso, seguía recibiendo este error cada vez y solo esta solución me ayudó.
[ Reposicionando el comentario de Bartłomiej Semańczyk como respuesta porque me resolvió el problema]
Necesitaba hacer Simulator> Restablecer contenido y configuración en la barra de menú del simulador para que esto comience a funcionar para mí.
[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];