Skip to content

Commit 53e4b41

Browse files
committed
Add interval to async utilities to supplement post render checks
Resolves #241 Resolves #393
1 parent 3f8bd7b commit 53e4b41

File tree

3 files changed

+262
-35
lines changed

3 files changed

+262
-35
lines changed

Diff for: docs/api-reference.md

+57-18
Original file line numberDiff line numberDiff line change
@@ -152,50 +152,90 @@ variable to `true` before importing `@testing-library/react-hooks` will also dis
152152
### `waitForNextUpdate`
153153
154154
```js
155-
function waitForNextUpdate(options?: WaitOptions): Promise<void>
155+
function waitForNextUpdate(options?: {
156+
timeout?: number
157+
}): Promise<void>
156158
```
157159

158160
Returns a `Promise` that resolves the next time the hook renders, commonly when state is updated as
159161
the result of an asynchronous update.
160162

161-
See the [`wait` Options](/reference/api#wait-options) section for more details on the available
162-
`options`.
163+
#### `timeout`
163164

164-
### `wait`
165+
The maximum amount of time in milliseconds (ms) to wait. By default, no timeout is applied.
166+
167+
### `waitFor`
165168

166169
```js
167-
function wait(callback: function(): boolean|void, options?: WaitOptions): Promise<void>
170+
function waitFor(callback: function(): boolean|void, options?: {
171+
interval?: number,
172+
timeout?: number,
173+
suppressErrors?: boolean
174+
}): Promise<void>
168175
```
169176

170177
Returns a `Promise` that resolves if the provided callback executes without exception and returns a
171178
truthy or `undefined` value. It is safe to use the [`result` of `renderHook`](/reference/api#result)
172179
in the callback to perform assertion or to test values.
173180

174-
The callback is tested after each render of the hook. By default, errors raised from the callback
175-
will be suppressed (`suppressErrors = true`).
181+
#### `interval`
176182

177-
See the [`wait` Options](/reference/api#wait-options) section for more details on the available
178-
`options`.
183+
The amount of time in milliseconds (ms) to wait between checks of the callback if no renders occur.
184+
By default, an interval of 50ms is used.
185+
186+
#### `timeout`
187+
188+
The maximum amount of time in milliseconds (ms) to wait. By default, no timeout is applied.
189+
190+
#### `suppressErrors`
191+
192+
If this option is set to `true`, any errors that occur while waiting are treated as a failed check.
193+
If this option is set to `false`, any errors that occur while waiting cause the promise to be
194+
rejected. By default, errors are suppressed for this utility.
179195

180196
### `waitForValueToChange`
181197

182198
```js
183-
function waitForValueToChange(selector: function(): any, options?: WaitOptions): Promise<void>
199+
function waitForValueToChange(selector: function(): any, options?: {
200+
interval?: number,
201+
timeout?: number,
202+
suppressErrors?: boolean
203+
}): Promise<void>
184204
```
185205

186206
Returns a `Promise` that resolves if the value returned from the provided selector changes. It
187207
expected that the [`result` of `renderHook`](/reference/api#result) to select the value for
188208
comparison.
189209

190-
The value is selected for comparison after each render of the hook. By default, errors raised from
191-
selecting the value will not be suppressed (`suppressErrors = false`).
210+
#### `interval`
211+
212+
The amount of time in milliseconds (ms) to wait between checks of the callback if no renders occur.
213+
By default, an interval of 50ms is used.
214+
215+
#### `timeout`
216+
217+
The maximum amount of time in milliseconds (ms) to wait. By default, no timeout is applied.
218+
219+
#### `suppressErrors`
192220

193-
See the [`wait` Options](/reference/api#wait-options) section for more details on the available
194-
`options`.
221+
If this option is set to `true`, any errors that occur while waiting are treated as a failed check.
222+
If this option is set to `false`, any errors that occur while waiting cause the promise to be
223+
rejected. By default, errors are not suppressed for this utility.
195224

196-
### `wait` Options
225+
### `wait`
197226

198-
The async utilities accept the following options:
227+
_(DEPRECATED, use [`waitFor`](/reference/api#waitFor) instead)_
228+
229+
```js
230+
function waitFor(callback: function(): boolean|void, options?: {
231+
timeout?: number,
232+
suppressErrors?: boolean
233+
}): Promise<void>
234+
```
235+
236+
Returns a `Promise` that resolves if the provided callback executes without exception and returns a
237+
truthy or `undefined` value. It is safe to use the [`result` of `renderHook`](/reference/api#result)
238+
in the callback to perform assertion or to test values.
199239

200240
#### `timeout`
201241

@@ -205,5 +245,4 @@ The maximum amount of time in milliseconds (ms) to wait. By default, no timeout
205245

206246
If this option is set to `true`, any errors that occur while waiting are treated as a failed check.
207247
If this option is set to `false`, any errors that occur while waiting cause the promise to be
208-
rejected. Please refer to the [utility descriptions](/reference/api#async-utilities) for the default
209-
values of this option (if applicable).
248+
rejected. By default, errors are suppressed for this utility.

Diff for: src/asyncUtils.js

+30-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ function createTimeoutError(utilName, { timeout }) {
66
return timeoutError
77
}
88

9+
function resolveAfter(ms) {
10+
return new Promise((resolve) => {
11+
setTimeout(resolve, ms)
12+
})
13+
}
14+
15+
let hasWarnedDeprecatedWait = false
16+
917
function asyncUtils(addResolver) {
1018
let nextUpdatePromise = null
1119

@@ -30,7 +38,7 @@ function asyncUtils(addResolver) {
3038
await nextUpdatePromise
3139
}
3240

33-
const wait = async (callback, { timeout, suppressErrors = true } = {}) => {
41+
const waitFor = async (callback, { interval = 50, timeout, suppressErrors = true } = {}) => {
3442
const checkResult = () => {
3543
try {
3644
const callbackResult = callback()
@@ -47,13 +55,13 @@ function asyncUtils(addResolver) {
4755
while (true) {
4856
const startTime = Date.now()
4957
try {
50-
await waitForNextUpdate({ timeout })
58+
await Promise.race([waitForNextUpdate({ timeout }), resolveAfter(interval)])
5159
if (checkResult()) {
5260
return
5361
}
5462
} catch (e) {
5563
if (e.timeout) {
56-
throw createTimeoutError('wait', { timeout: initialTimeout })
64+
throw createTimeoutError('waitFor', { timeout: initialTimeout })
5765
}
5866
throw e
5967
}
@@ -69,7 +77,7 @@ function asyncUtils(addResolver) {
6977
const waitForValueToChange = async (selector, options = {}) => {
7078
const initialValue = selector()
7179
try {
72-
await wait(() => selector() !== initialValue, {
80+
await waitFor(() => selector() !== initialValue, {
7381
suppressErrors: false,
7482
...options
7583
})
@@ -81,8 +89,26 @@ function asyncUtils(addResolver) {
8189
}
8290
}
8391

92+
const wait = async (callback, { timeout, suppressErrors } = {}) => {
93+
if (!hasWarnedDeprecatedWait) {
94+
hasWarnedDeprecatedWait = true
95+
console.warn(
96+
'`wait` has been deprecated. Use `waitFor` instead: https://react-hooks-testing-library.com/reference/api#waitFor.'
97+
)
98+
}
99+
try {
100+
await waitFor(callback, { timeout, suppressErrors })
101+
} catch (e) {
102+
if (e.timeout) {
103+
throw createTimeoutError('wait', { timeout })
104+
}
105+
throw e
106+
}
107+
}
108+
84109
return {
85110
wait,
111+
waitFor,
86112
waitForNextUpdate,
87113
waitForValueToChange
88114
}

0 commit comments

Comments
 (0)