Selects dinámicos con React Select en Cypress

Resumen

Probar formularios con select y dropdowns dinámicos es una de las tareas más comunes (y a veces más frustrantes) cuando automatizas pruebas con Cypress. Aquí aprenderás a interactuar con listas desplegables tradicionales y con componentes modernos como React Select, usando comandos nativos y algunos trucos cuando el HTML no coopera.

¿Cómo seleccionar elementos en un select tradicional con Cypress?

Cuando trabajas con un <select> clásico de HTML, Cypress te ofrece el comando .select(), que permite elegir opciones de tres formas distintas según lo que tengas a la mano [2:00].

Lo primero es ubicar el elemento. En el formulario de prueba, el select tiene una clase llamada custom-select, así que lo obtienes con cy.get('.custom-select') y a partir de ahí encadenas la selección.

¿Qué formas existen para seleccionar una opción?

Tienes tres caminos según el dato que conozcas de la opción:

  • Por índice numérico: .select(10) toma la opción número 10 de la lista. En el ejemplo, ese índice corresponde a Finlandia.
  • Por valor (string): .select('3') selecciona la opción cuyo value es la cadena "3", que en el formulario corresponde a Turquía.
  • Por texto visible: .select('Greece') selecciona la opción por su label, y puedes confirmar con .should('have.value', '4').

¿Cuál es la diferencia entre seleccionar por valor y por texto? El valor es el atributo value del <option> (suele ser un ID o número como string), mientras que el texto es lo que el usuario realmente ve. Selecciona por texto cuando quieres pruebas más legibles.

En el ejemplo, encadenar la aserción .should('have.value', '4') después de .select('Greece') valida que la opción correcta quedó activa, todo en una sola línea.

¿Cómo trabajar con dropdowns dinámicos como React Select?

Los dropdowns construidos con librerías modernas ya no son <select> reales, sino combinaciones de <div> e <input> de tipo texto que simulan el comportamiento. Esto los hace más bonitos para el usuario, pero más difíciles de automatizar [6:30].

El comando .select() de Cypress no funciona aquí, así que necesitas otra estrategia: localizar el input interno, abrir la lista y hacer clic sobre la opción deseada.

¿Cómo abro la lista de opciones en React Select?

Primero localizas el input por su ID (en el ejemplo, react-select-6-input) y le envías un .type(' ') con un espacio en blanco. Ese pequeño truco despliega todas las opciones disponibles sin filtrar nada [9:15].

Una vez abierto el listado, el contenedor real de las opciones tiene otro ID, como react-select-6-listbox. Desde ahí puedes navegar a sus hijos para llegar a cada opción.

¿Cómo selecciono una opción por texto en un dropdown dinámico?

Cuando no conoces el índice exacto, puedes iterar sobre las opciones con .each(), que recibe un callback con tres parámetros: el elemento, el índice y la lista completa.

javascript cy.get('#react-select-6-listbox') .children() .children() .each(($el, index, $list) => { if ($el.text() === 'red') { cy.wrap($el).click() } })

Dentro del callback comparas $el.text() con el valor que buscas y, si coincide, haces clic. Aquí entra en juego cy.wrap() para envolver el elemento de jQuery y poder usar comandos de Cypress sobre él.

¿Qué hace .children() en Cypress? Devuelve los hijos directos de un elemento. Encadenarlo dos veces te permite bajar dos niveles en el DOM, útil cuando las opciones están anidadas dentro de varios div contenedores.

¿Hay una forma más directa si conozco el índice?

Sí, y es bastante más limpia. Si ya sabes el ID o el índice de la opción, puedes ir directo con un cy.get():

javascript cy.get('#react-select-6-option-3').click()

Esta sintaxis es la ideal cuando la librería expone IDs predecibles. Cambias el número final y seleccionas otra opción sin recorrer toda la lista [13:40].

¿Por qué los dropdowns modernos son más difíciles de automatizar?

La razón es que dejaron de ser un <select> nativo. Hoy un componente como React Select combina un <input type="text"> editable con una lista renderizada como <div>, y todo eso se monta y desmonta dinámicamente según la interacción del usuario.

Esto trae ventajas visuales y de UX, pero te obliga a:

  • Inspeccionar el DOM con cuidado para identificar IDs estables.
  • Usar comandos como .children(), .each() y cy.wrap() para navegar estructuras anidadas.
  • Conocer la convención de nombres de la librería (en React Select todo sigue el patrón react-select-N-...).

Una nota técnica: al usar $el.click() directamente verás una advertencia de que es la forma deprecated en jQuery. Por eso es mejor envolver con cy.wrap($el).click(), que es el camino recomendado dentro del ecosistema de Cypress.

¿Has tenido que automatizar un dropdown especialmente complicado? Cuéntame en los comentarios qué librería usabas y cómo lo resolviste.