跳至主要內容

非同步方法

提供數個工具來處理非同步程式碼。這些工具可用於等待元素因應事件、使用者動作、逾時或 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