Error de prueba de IU: ni el elemento ni ningún descendiente tienen el foco del teclado en secureTextField

139

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 la normalidad textFields, pero el problema solo surge con secureTextFields. ¿Alguna solución?

Bartłomiej Semańczyk
fuente
y la parte extraña es que si lo intento así, funciona XCUIApplication (). webViews.secureTextFields ["Password"]. tap () XCUIApplication (). webViews.secureTextFields ["Password"]. typeText ("Welcome")
aurilio
Es posible que haya configurado el identificador de accesibilidad pero no ha configurado isAccessibilityElement = true
soumil
He agregado una respuesta a una pregunta similar aquí: stackoverflow.com/a/59637897/2585413 . Mi problema era que tenía otras UIWindows con valores .windowLevel incorrectos
nteissler

Respuestas:

264

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.

Ted Kaminski
fuente
44
Esto ha solucionado el problema. Pero es una solución muy pobre, ya que no podemos aplicarla automáticamente para CI.
Stanislav Pankevich
25
Si ejecuta sus pruebas en CI (Jenkins, etc.) Puede configurar los siguientes parámetros en un script antes de ejecutar sus pruebas. "valores predeterminados escriben com.apple.iphonesimulator ConnectHardwareKeyboard 0"
charlyatwork
77
Esto no resuelve el problema para mí. Puedo ver claramente el campo de texto obtención de enfoque, con el teclado hacia arriba, pero el marco de pruebas nunca puede introducir texto con el TypeText: Método
Michael
2
Me funcionó en Xcode 11, pero desmarcar Conectar teclado de hardware puede no ser suficiente. Además, uno debe asegurarse de que realmente se muestre el teclado del software (en realidad, tuve la situación de que no estaba conectado ningún teclado de hardware y no se mostró ningún teclado de software, incluso si el textField tenía el foco y el cursor parpadeaba).
Reinhard Männer
1
Me encontré con esto en Xcode 11 también. Se soluciona localmente, pero ¿cómo se puede configurar esto en CI?
jherg
26

Recientemente encontramos un hack 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.

AlexDenisov
fuente
Esto no ha cambiado algo.
netshark1000
@ netshark1000 que se puede cambiar con la versión más nueva de Xcode, lo comprobaré.
AlexDenisov
1
extremadamente útil, necesitaba lo contrario donde el teclado siempre está habilitado, pero sí, esto es genial, gracias. Terminé yendo con defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool true, pero es el mismo concepto.
Laser Hawk el
2
Creé un script en las fases de construcción para hacerlo. Pero necesitaba matar a todos los simuladores, así que hice eso:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
Wagner Sales el
Esto ya no parece funcionar, ¿ha cambiado la clave? @AlexDenisov
Simon McLoughlin
15

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.

berezhnyi oleksandr
fuente
Esto no está funcionando para mí en este momento. Tengo Xcode 7.2 (7C68), ¿qué versión tienes? Esta solución que encontramos para CI funciona para nosotros: stackoverflow.com/a/34812979/598057 .
Stanislav Pankevich
Para confirmarlo una vez más: ¿este ayudante funciona para usted para el campo de texto de contraseña segura y no solo para el campo de texto normal?
Stanislav Pankevich
Sí, funciona para ambos tipos de campo de texto: regular y seguro.
berezhnyi oleksandr
1
El problema con esta respuesta es que usa un retraso codificado. En su lugar, use el modelo de espera de expectativas con el elemento del teclado.
user1122069
11

Stanislav tiene la idea correcta.

En un entorno de equipo, necesita algo que funcione automáticamente. He encontrado una solución aquí 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()
RyanPliske
fuente
Gracias por compartir su solución. Desafortunadamente no está funcionando para mí en este momento. Estoy teniendo Xcode 7.2 (7C68), ¿y tú? Vea otra solución que encontramos para CI: stackoverflow.com/questions/32184837/… .
Stanislav Pankevich
8

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 intenté ingresar texto en una UISearchBar. La barra de búsqueda en sí no es el campo de texto, al configurarlo como un elemento de accesibilidad, se bloqueó el acceso al UITextField subyacente. Para resolver esto, searchBar.accessibilityIdentifier = "My Identifier"se estableció en UISearchBarsin embargo, isAccessibilityElementno se configuró 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

usuario3847320
fuente
6

Ocurrió conmigo muchas veces. Debe deshabilitar el hardware del teclado y el mismo diseño que OSX en su simulador

Hardware / Teclado (deshabilitar todo)

Después de eso, el software del teclado no se descartará y sus pruebas pueden escribir texto

Deshabilitar hardware

Fernando Martínez
fuente
5

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ó.

Kingalione
fuente
1
El problema es que si tiene una gran cantidad de pruebas de IU que realizan algo como un inicio de sesión inicial, esto agregará una gran sobrecarga a su ejecución de prueba de CI.
delta2flat
4

Esto quizás ayude: acabo de agregar una acción de "toque" antes del error; eso es todo :)

[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];
Carlos Peralta
fuente
2
Esto definitivamente no funciona para el campo de texto de contraseña segura.
Stanislav Pankevich
Esto funcionó para mi campo de texto de contraseña segura bien. Buena solución.
Travis M.
4
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()
}
Antonio
fuente
4

Grabe el caso como lo desee, teclado o sin teclado conectado. Pero haga lo siguiente antes de jugar la prueba.

La siguiente opción (conectar el teclado de hardware) debe estar desmarcada mientras se reproduce la prueba.

ingrese la descripción de la imagen aquí

umairhhhs
fuente
4

En mi caso esto Hardware -> Keyboard -> Connect Hardware Keyboard-> Deshabilitar no funcionó para mí.

Pero cuando lo seguí

1) Hardware -> Keyboard -> Connect Hardware Keyboard-> Habilitado y ejecute la aplicación
2) Hardware -> Keyboard -> Connect Hardware Keyboard-> Deshabilitado .

Funciono para mi

BharathRao
fuente
Me funcionó, HOMBRE ¡Odio este aspecto de XCode!
bwobbones
3

[ 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í.

rogueleaderr
fuente
Restablecer el simulador también me ayudó. Curiosamente, el problema solo ocurrió en el simulador, mientras que la misma prueba (toque texfield seguido de caracteres de mecanografía) funcionó bien en un dispositivo.
Christian
1

En ocasiones, los campos de texto no se implementan como campos de texto, o se envuelven en otro elemento de la interfaz de usuario 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()       

Eugene Berezin
fuente
0

Su primera línea es solo una definición de consulta , lo que no significa quepasswordSecureTextField realmente exista.

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, tapdebería forzar el teclado visible y luego typeTextdebería funcionar. El registro de errores debería decirle más información.

JOM
fuente
1
passwordSecureTextFieldexiste Solucioné el problema, pero limpié la memoria y reescribí esas líneas nuevamente. Extraño, pero funcionó.
Bartłomiej Semańczyk
Es bueno saber que está arreglado! Me encontré con un problema similar ayer con beta 6 :)
JOM
beta 6? :-) realmente? Solo tengo 5 :)
Bartłomiej Semańczyk
Has estado ocupado codificando :) Beta 6 no grabó tappara mí, me tomó un tiempo descubrirlo. ¡Buena práctica de depuración!
JOM
Quizás conozca la respuesta para esto: stackoverflow.com/questions/32219015/… ?
Bartłomiej Semańczyk
0

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.

codercat
fuente
0

El problema para mí era el mismo que para Ted. En realidad, si el campo de contraseña se toca después del campo de inicio de sesión y 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 pruebas 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 Run Scriptfase en las fases de compilación y usarlo así: osascript Path/To/Script/script_name.applescript

Timur Kuchkarov
fuente
0

Encontramos el mismo error al configurar el accessibilityIdentifier valor para una vista personalizada ( UIStackViewsubclase) que contiene UIControlsubvistas. En ese caso, XCTest no pudo obtener el foco del teclado para los elementos descendientes.

Nuestra solución fue simplemente eliminar el accessibilityIdentifierde nuestra vista principal y establecer el accessibilityIdentifierpara las subvistas a través de propiedades dedicadas.

caballo de las sombras
fuente
0

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. Verificación de fuente fresca.

David J
fuente
0

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)
Przemysław Wrzesiński
fuente
0

Me encontré con este problema y pude solucionarlo en mi escenario al tomar la solución publicada por @AlexDenisov y agregarla a mis acciones previas para ejecutar y probar .

ingrese la descripción de la imagen aquí

CodeBender
fuente
0

No es necesario encender / apagar el teclado en E / S. No use .typeText para secureTextField, solo use

app.keys["p"].tap()
app.keys["a"].tap()
app.keys["s"].tap()
app.keys["s"].tap()

Bonificación: obtienes clic de sonido del teclado :)

zdravko zdravkin
fuente
0

Finalmente, escribí un script que edita el archivo .plist del Simulador y establece el ConnectHardwareKeyboard propiedad en falso para el simulador seleccionado. Lo escuchaste bien, cambia la propiedad del simulador específicamente seleccionado dentro del diccionario "DevicePreferences" en lugar de editar la propiedad global.

Primero, cree un script de shell llamado disable-hardware-keyboard.sh con los siguientes contenidos. Puede colocarlo dentro de "YourProject / xyzUITests / Scripts /" .:

echo "Script: Set ConnectHardwareKeyboard to false for given Simulator UDID"

if [[ $1 != *-*-*-*-* ]]; then
    echo "Pass device udid as first argument."
    exit 1
else
    DEVICE_ID=$1
fi

DEVICE_PREFERENCES_VALUE='<dict><key>ConnectHardwareKeyboard</key><false/></dict>'
killall Simulator # kill restart the simulator to make the plist changes picked up
defaults write com.apple.iphonesimulator DevicePreferences -dict-add $DEVICE_ID $DEVICE_PREFERENCES_VALUE
open -a Simulator # IMPORTANT

Ahora siga estos pasos para llamarlo pasando el udid del simulador seleccionado como argumento:

  1. Edite su esquema Xcode (o UI prueba un esquema específico si tiene uno)
  2. Vaya a: Prueba> Acciones previas
  3. Agregue un nuevo script tocando el símbolo "+"> "Nueva acción de ejecutar script".
  4. Importante: Dentro del menú desplegable "Proporcionar configuración de compilación desde", elija el objetivo principal de la aplicación, no el objetivo de las pruebas de IU.
  5. Ahora agregue el siguiente script en el área de texto a continuación.

Script dentro de Prueba> Pre-acciones:

#!/bin/sh
# $PROJECT_DIR is path to your source project. This is provided when we select "Provide build settings from" to "AppTarget"
# $TARGET_DEVICE_IDENTIFIER is the UDID of the selected simulator
sh $PROJECT_DIR/xyzUITests/Scripts/disable-hardware-keyboard.sh $TARGET_DEVICE_IDENTIFIER

# In order to see output of above script, append following with it:
#  | tee ~/Desktop/ui-test-scheme-prescript.txt

Hora de probarlo:

  1. Simulador de lanzamiento
  2. Habilitar teclado de hardware para ello
  3. Ejecute cualquier prueba de IU con interacción con el teclado. Observe que el simulador se reinicia y el teclado del hardware está deshabilitado. Y la interacción del teclado de la prueba está funcionando bien. :)
Hasaan Ali
fuente
-1

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")
Rads
fuente
¿Cuál es la diferencia entre su código y el código formulado en la pregunta?
Shivam Pokhriyal