Saltar al contenido principal

Métodos asíncronos

[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 →

Se proporcionan varias utilidades para manejar código asíncrono. Estas pueden ser útiles para esperar la aparición o desaparición de un elemento en respuesta a un evento, acción del usuario, tiempo de espera o Promise. (Consulta la guía para probar desapariciones).

Los métodos asíncronos devuelven Promises, así que asegúrate de usar await o .then al llamarlos.

Consultas findBy

Los métodos findBy combinan las consultas getBy y waitFor. Aceptan las opciones de waitFor como último argumento (ej. await screen.findByText('text', queryOptions, waitForOptions)).

Las consultas findBy funcionan cuando esperas que aparezca un elemento pero el cambio en el DOM podría no ocurrir inmediatamente.

const button = screen.getByRole('button', {name: 'Click Me'})
fireEvent.click(button)
await screen.findByText('Clicked once')
fireEvent.click(button)
await screen.findByText('Clicked twice')

waitFor

function waitFor<T>(
callback: () => T | Promise<T>,
options?: {
container?: HTMLElement
timeout?: number
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
},
): Promise<T>

Cuando necesites esperar cualquier período de tiempo, puedes usar waitFor para esperar que se cumplan tus expectativas. Devolver una condición falsa no es suficiente para activar un reintento; el callback debe lanzar un error para reintentar la condición. Aquí un ejemplo simple:

// ...
// Wait until the callback does not throw an error. In this case, that means
// it'll wait until the mock function has been called once.
await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
// ...

waitFor puede ejecutar el callback múltiples veces hasta alcanzar el timeout. Ten en cuenta que la cantidad de llamadas está limitada por las opciones timeout e interval.

Esto puede ser útil si tienes una prueba unitaria que simula llamadas API y necesitas esperar que todas las Promises simuladas se resuelvan.

Si devuelves una Promise en el callback de waitFor (explícitamente o implícitamente con sintaxis async), entonces la utilidad waitFor no llamará nuevamente tu callback hasta que esa Promise se rechace. Esto te permite waitFor cosas que deben verificarse asíncronamente.

El container predeterminado es el document global. Asegúrate que los elementos que esperas sean descendientes de container.

El interval predeterminado es 50ms. Sin embargo, ejecuta tu callback inmediatamente antes de iniciar los intervalos.

El timeout predeterminado es 1000ms.

El onTimeout predeterminado toma el error y añade el estado impreso del container al mensaje de error, lo que debería facilitar identificar la causa del timeout.

Las mutationObserverOptions predeterminadas son {subtree: true, childList: true, attributes: true, characterData: true}, que detectan adiciones y eliminaciones de elementos hijos (incluyendo nodos de texto) en el container y sus descendientes. También detecta cambios en atributos. Cuando ocurren estos cambios, se vuelve a ejecutar el callback.

waitForElementToBeRemoved

function waitForElementToBeRemoved<T>(
callback: (() => T) | T,
options?: {
container?: HTMLElement
timeout?: number
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
},
): Promise<void>

Para esperar la eliminación de elemento(s) del DOM, puedes usar waitForElementToBeRemoved. La función waitForElementToBeRemoved es un pequeño wrapper sobre la utilidad waitFor.

El primer argumento debe ser un elemento, un array de elementos, o un callback que devuelva un elemento o array de elementos.

Aquí un ejemplo donde la Promise se resuelve porque se elimina el elemento:

const el = document.querySelector('div.getOuttaHere')

waitForElementToBeRemoved(document.querySelector('div.getOuttaHere')).then(() =>
console.log('Element no longer in DOM'),
)

el.setAttribute('data-neat', true)
// other mutations are ignored...

el.parentElement.removeChild(el)
// logs 'Element no longer in DOM'

waitForElementToBeRemoved lanza un error si el primer argumento es null o un array vacío:

waitForElementToBeRemoved(null).catch(err => console.log(err))
waitForElementToBeRemoved(queryByText(/not here/i)).catch(err =>
console.log(err),
)
waitForElementToBeRemoved(queryAllByText(/not here/i)).catch(err =>
console.log(err),
)
waitForElementToBeRemoved(() => getByText(/not here/i)).catch(err =>
console.log(err),
)

// Error: The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.

El objeto de opciones se reenvía a waitFor.