跳至主要内容

异步方法

提供了一些用于处理异步代码的实用程序。这些方法在等待元素响应事件、用户操作、超时或 Promise 出现或消失时非常有用。(参见 测试消失的指南。)

异步方法返回 Promise,因此在调用它们时请确保使用 await.then

findBy 查询

findBy 方法结合了 getBy 查询waitFor。它们接受 waitFor 选项作为最后一个参数(例如 await screen.findByText('text', queryOptions, waitForOptions))。

当您希望元素出现,但 DOM 更改可能不会立即发生时,findBy 查询非常有用。

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>

当需要等待一段时间时,可以使用 waitFor 来等待您的预期通过。返回假值条件不足以触发重试,回调必须抛出错误才能重试条件。这是一个简单的示例

// ...
// 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 可能会多次运行回调,直到达到超时时间。请注意,调用次数受 timeoutinterval 选项的限制。

这在您有一个模拟 API 调用的单元测试,并且需要等待您的模拟 Promise 全部解析时非常有用。

如果您在 waitFor 回调中返回 Promise(无论是显式地还是使用 async 语法隐式地),那么 waitFor 实用程序在该 Promise 拒绝之前不会再次调用您的回调。这允许您 waitFor 必须异步检查的事项。

默认的 container 是全局 document。确保您等待的元素是 container 的后代。

默认的 interval50ms。但是它会在启动间隔之前立即运行您的回调。

默认的 timeout1000ms

默认的 onTimeout 获取错误并将 container 的打印状态附加到错误消息,这应该有助于更容易地追踪导致超时的原因。

默认的 mutationObserverOptions{subtree: true, childList: true, attributes: true, characterData: true},它检测 container 及其任何后代中子元素(包括文本节点)的添加和删除。它还检测属性更改。当发生任何这些更改时,它将重新运行回调。

waitForElementToBeRemoved

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

要等待从 DOM 中删除元素,可以使用 waitForElementToBeRemovedwaitForElementToBeRemoved 函数是 waitFor 实用程序的一个小型包装器。

第一个参数必须是元素、元素数组或返回元素或元素数组的回调。

这是一个示例,其中 Promise 因为元素被删除而解析

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'

如果第一个参数为 null 或空数组,则 waitForElementToBeRemoved 会抛出错误

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.

选项对象被转发到 waitFor