Saltar al contenido principal

Acerca de las consultas

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Resumen

Las consultas son los métodos que Testing Library proporciona para encontrar elementos en la página. Existen varios tipos de consultas ("get", "find", "query"); la diferencia entre ellos radica en si la consulta lanzará un error cuando no se encuentre ningún elemento o si retornará una Promise y reintentará. Dependiendo del contenido de la página que estés seleccionando, diferentes consultas pueden ser más o menos apropiadas. Consulta la guía de prioridad para recomendaciones sobre cómo utilizar consultas semánticas y probar tu página de la manera más accesible.

Después de seleccionar un elemento, puedes usar la API de Eventos o user-event para disparar eventos y simular interacciones de usuario con la página, o utilizar Jest y jest-dom para realizar aserciones sobre el elemento.

Existen métodos auxiliares de Testing Library que funcionan con consultas. A medida que los elementos aparecen y desaparecen en respuesta a acciones, se pueden usar APIs asíncronas como waitFor o consultas findBy para esperar los cambios en el DOM. Para encontrar solo elementos que sean hijos de un elemento específico, puedes usar within. Si es necesario, también hay opciones que puedes configurar, como el tiempo de espera para reintentos y el atributo testID predeterminado.

Ejemplo

import {render, screen} from '@testing-library/react' // (or /dom, /vue, ...)

test('should show login form', () => {
render(<Login />)
const input = screen.getByLabelText('Username')
// Events and assertions...
})

Tipos de consultas

  • Elementos únicos

    • getBy...: Retorna el nodo coincidente para una consulta, y lanza un error descriptivo si no se encuentran elementos o si se encuentra más de una coincidencia (usa getAllBy si se espera más de un elemento).
    • queryBy...: Retorna el nodo coincidente para una consulta, y retorna null si no se encuentran elementos. Útil para verificar que un elemento no está presente. Lanza un error si se encuentra más de una coincidencia (usa queryAllBy si esto es aceptable).
    • findBy...: Retorna una Promise que se resuelve cuando se encuentra un elemento que coincide con la consulta. La promise se rechaza si no se encuentra ningún elemento o si se encuentra más de un elemento después de un tiempo de espera predeterminado de 1000ms. Si necesitas encontrar más de un elemento, usa findAllBy.
  • Múltiples elementos

    • getAllBy...: Retorna un array de todos los nodos coincidentes para una consulta, y lanza un error si no se encuentran elementos.
    • queryAllBy...: Retorna un array de todos los nodos coincidentes para una consulta, y retorna un array vacío ([]) si no se encuentran elementos.
    • findAllBy...: Retorna una promise que se resuelve en un array de elementos cuando se encuentran elementos que coinciden con la consulta. La promise se rechaza si no se encuentran elementos después de un tiempo de espera predeterminado de 1000ms.
      • Los métodos findBy combinan consultas getBy* y waitFor. Aceptan las opciones de waitFor como último argumento (ej. await screen.findByText('text', queryOptions, waitForOptions))
Summary Table

Type of Query0 Matches1 Match>1 MatchesRetry (Async/Await)
Single Element
getBy...Throw errorReturn elementThrow errorNo
queryBy...Return nullReturn elementThrow errorNo
findBy...Throw errorReturn elementThrow errorYes
Multiple Elements
getAllBy...Throw errorReturn arrayReturn arrayNo
queryAllBy...Return []Return arrayReturn arrayNo
findAllBy...Throw errorReturn arrayReturn arrayYes

Prioridad

Basado en los Principios rectores, tus pruebas deben imitar cómo los usuarios interactúan con tu código (componente, página, etc.) tanto como sea posible. Con esto en mente, recomendamos este orden de prioridad:

  1. Consultas accesibles para todos: Consultas que reflejan la experiencia de usuarios visuales/de ratón y quienes utilizan tecnologías asistivas.

    1. getByRole: Puede usarse para consultar cada elemento expuesto en el árbol de accesibilidad. Con la opción name puedes filtrar elementos por su nombre accesible. Debería ser tu primera opción para casi todo. Es raro que no puedas obtener algo con esto (si no puedes, posiblemente tu UI sea inaccesible). Normalmente se usa con la opción name así: getByRole('button', {name: /submit/i}). Consulta la lista de roles.
    2. getByLabelText: Ideal para campos de formulario. Al navegar formularios, los usuarios encuentran elementos mediante etiquetas. Este método emula ese comportamiento, siendo preferible.
    3. getByPlaceholderText: Un placeholder no sustituye una etiqueta. Pero si es lo único disponible, es mejor que alternativas.
    4. getByText: Fuera de formularios, el contenido textual es cómo los usuarios encuentran elementos. Útil para elementos no interactivos (divs, spans, párrafos).
    5. getByDisplayValue: El valor actual de elementos de formulario ayuda al navegar páginas con valores prellenados.
  2. Consultas semánticas: Selectores compatibles con HTML5 y ARIA. Nota: la experiencia de usuario con estos atributos varía entre navegadores y tecnologías asistivas.

    1. getByAltText: Si tu elemento soporta texto alt (img, area, input, elementos personalizados), úsalo para encontrarlo.
    2. getByTitle: El atributo title no es leído consistentemente por lectores de pantalla ni visible por defecto para usuarios videntes.
  3. IDs de prueba

    1. getByTestId: Los usuarios no ven/oyen estos, solo recomendado cuando no puedes hacer match por rol/texto o no tiene sentido (ej. texto dinámico).

Uso de consultas

Las consultas base de DOM Testing Library requieren pasar un container como primer argumento. La mayoría de implementaciones para frameworks proporcionan versiones previnculadas al renderizar componentes, evitando especificar contenedores. Además, para consultar document.body puedes usar el export screen como se muestra abajo (se recomienda screen).

El argumento principal de una consulta puede ser string, expresión regular o función. Hay opciones para ajustar cómo se analiza el texto. Ver TextMatch para documentación sobre qué puede pasarse.

Dados los siguientes elementos DOM (renderizados por React, Vue, Angular o HTML simple):

<body>
<div id="app">
<label for="username-input">Username</label>
<input id="username-input" />
</div>
</body>

Puedes usar una consulta para encontrar un elemento (en este caso, byLabelText):

import {screen, getByLabelText} from '@testing-library/dom'

// With screen:
const inputNode1 = screen.getByLabelText('Username')

// Without screen, you need to provide a container:
const container = document.querySelector('#app')
const inputNode2 = getByLabelText(container, 'Username')

queryOptions

Puedes pasar un objeto queryOptions con el tipo de consulta. Consulta la documentación de cada tipo para ver opciones disponibles, ej. API byRole.

screen

Todas las consultas exportadas por DOM Testing Library aceptan un container como primer argumento. Dado que consultar todo el document.body es muy común, DOM Testing Library también exporta un objeto screen que contiene todas las consultas previnculadas a document.body (usando la funcionalidad within). Wrappers como React Testing Library reexportan screen para que puedas usarlo de la misma manera.

Así es como se usa:

import {screen} from '@testing-library/dom'

document.body.innerHTML = `
<label for="example">Example</label>
<input id="example" />
`

const exampleInput = screen.getByLabelText('Example')

Nota

Necesitas un entorno DOM global para usar screen. Si usas Jest con testEnvironment configurado como jsdom, tendrás disponible un entorno DOM global.

Si cargas tu prueba con una etiqueta script, asegúrate de que venga después del body. Puedes ver un ejemplo aquí.

TextMatch

La mayoría de las APIs de consulta aceptan un TextMatch como argumento, lo que significa que puede ser una cadena, una expresión regular o una función con firma (content?: string, element?: Element | null) => boolean que retorna true para coincidencia y false para no coincidencia.

Ejemplos de TextMatch

Dado el siguiente HTML:

<div>Hello World</div>

Encontrará el div:

// Matching a string:
screen.getByText('Hello World') // full string match
screen.getByText('llo Worl', {exact: false}) // substring match
screen.getByText('hello world', {exact: false}) // ignore case

// Matching a regex:
screen.getByText(/World/) // substring match
screen.getByText(/world/i) // substring match, ignore case
screen.getByText(/^hello world$/i) // full string match, ignore case
screen.getByText(/Hello W?oRlD/i) // substring match, ignore case, searches for "hello world" or "hello orld"

// Matching with a custom function:
screen.getByText((content, element) => content.startsWith('Hello'))

No encontrará el div:

// full string does not match
screen.getByText('Goodbye World')

// case-sensitive regex with different case
screen.getByText(/hello world/)

// function looking for a span when it's actually a div:
screen.getByText((content, element) => {
return element.tagName.toLowerCase() === 'span' && content.startsWith('Hello')
})

Precisión

Las consultas que aceptan TextMatch también admiten un objeto como último argumento con opciones que afectan la precisión de coincidencia de cadenas:

  • exact: Por defecto true; coincide con cadenas completas, sensible a mayúsculas. Cuando es false, coincide con subcadenas sin distinguir mayúsculas/minúsculas.

    • No tiene efecto cuando se usa con argumentos regex o function.
    • En la mayoría de casos, usar una expresión regular en vez de una cadena con { exact: false } da más control sobre coincidencias aproximadas, por lo que es preferible.
  • normalizer: Función opcional que sobreescribe el comportamiento de normalización. Ver Normalization.

Normalización

Antes de aplicar cualquier lógica de coincidencia sobre texto en el DOM, DOM Testing Library normaliza automáticamente ese texto. Por defecto, la normalización incluye recortar espacios en blanco al inicio/final del texto y colapsar múltiples espacios adyacentes dentro de la cadena en un solo espacio.

Si deseas prevenir esta normalización o proporcionar una normalización alternativa (ej. para remover caracteres Unicode de control), puedes proveer una función normalizer en el objeto de opciones. Esta función recibirá una cadena y debe retornar una versión normalizada de la misma.

Nota

Especificar un valor para normalizer reemplaza la normalización incorporada, pero puedes llamar a getDefaultNormalizer para obtener un normalizador integrado, ya sea para ajustar esa normalización o llamarlo desde tu propio normalizador.

getDefaultNormalizer acepta un objeto de opciones que permite seleccionar comportamientos:

  • trim: Por defecto true. Recorta espacios en blanco iniciales y finales.

  • collapseWhitespace: Por defecto true. Colapsa espacios internos (saltos de línea, tabulaciones, espacios repetidos) en un solo espacio.

Ejemplos de Normalización

Para realizar una coincidencia sin recortar texto:

screen.getByText('text', {
normalizer: getDefaultNormalizer({trim: false}),
})

Para sobreescribir la normalización removiendo algunos caracteres Unicode mientras se mantiene parte (no toda) del comportamiento de normalización incorporado:

screen.getByText('text', {
normalizer: str =>
getDefaultNormalizer({trim: false})(str).replace(/[\u200E-\u200F]*/g, ''),
})

Consultas Manuales

Además de las consultas proporcionadas por la biblioteca de pruebas, puedes utilizar la API DOM regular querySelector para buscar elementos. Ten en cuenta que usar esto como solución alternativa para consultar por clase o ID no es recomendable porque son invisibles para el usuario. Si es necesario, utiliza un testid para dejar clara tu intención de recurrir a consultas no semánticas y establecer un contrato de API estable en el HTML.

// @testing-library/react
const {container} = render(<MyComponent />)
const foo = container.querySelector('[data-foo="bar"]')

Extensión de navegador

¿Sigues teniendo problemas para entender cómo usar las consultas de Testing Library?

Existe una extensión de navegador muy útil para Chrome llamada Testing Playground que te ayuda a encontrar las mejores consultas para seleccionar elementos. Te permite inspeccionar las jerarquías de elementos en las Herramientas de Desarrollo del navegador y ofrece sugerencias sobre cómo seleccionarlos, fomentando buenas prácticas de pruebas.

Entorno de pruebas

Si deseas familiarizarte más con estas consultas, puedes probarlas en testing-playground.com. Testing Playground es un entorno interactivo donde puedes ejecutar diferentes consultas contra tu propio HTML y obtener retroalimentación visual que sigue las reglas mencionadas anteriormente.