异步方法
提供了一些用于处理异步代码的实用程序。这些方法在等待元素响应事件、用户操作、超时或 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
可能会多次运行回调,直到达到超时时间。请注意,调用次数受 timeout
和 interval
选项的限制。
这在您有一个模拟 API 调用的单元测试,并且需要等待您的模拟 Promise 全部解析时非常有用。
如果您在 waitFor
回调中返回 Promise(无论是显式地还是使用 async
语法隐式地),那么 waitFor
实用程序在该 Promise 拒绝之前不会再次调用您的回调。这允许您 waitFor
必须异步检查的事项。
默认的 container
是全局 document
。确保您等待的元素是 container
的后代。
默认的 interval
是 50ms
。但是它会在启动间隔之前立即运行您的回调。
默认的 timeout
是 1000ms
。
默认的 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 中删除元素,可以使用 waitForElementToBeRemoved
。waitForElementToBeRemoved
函数是 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
。