@@ -7,116 +7,103 @@ Several utilities are provided for dealing with asynchronous code. These can be
7
7
useful to wait for an element to appear or disappear in response to an action.
8
8
(See the [ guide to testing disappearance] ( guide-disappearance.md ) .)
9
9
10
+ All the async utils are built on top of ` wait ` .
11
+
10
12
## ` wait `
11
13
12
14
``` typescript
13
- function wait(
14
- callback ? : () => void ,
15
+ function wait< T > (
16
+ callback : () => void ,
15
17
options ? : {
18
+ container? : HTMLElement
16
19
timeout? : number
17
20
interval? : number
21
+ mutationObserverOptions? : MutationObserverInit
18
22
}
19
- ): Promise <void >
23
+ ): Promise <T >
20
24
```
21
25
22
- When in need to wait for non - deterministic periods of time you can use ` wait ` ,
23
- to wait for your expectations to pass . The ` wait ` function is a small wrapper
24
- around the
25
- [`wait-for-expect`](https : // github.com/TheBrainFamily/wait-for-expect) module.
26
- Here ' s a simple example:
26
+ When in need to wait for any period of time you can use ` wait ` , to wait for your
27
+ expectations to pass . Here ' s a simple example:
27
28
28
29
` ` ` javascript
29
30
// ...
30
31
// Wait until the callback does not throw an error. In this case, that means
31
32
// it'll wait until we can get a form control with a label that matches "username".
32
- await wait(() => getByLabelText(container, 'username'))
33
- getByLabelText(container, 'username').value = 'chucknorris'
33
+ await wait(() => expect(mockAPI).toHaveBeenCalledTimes(1))
34
34
// ...
35
35
` ` `
36
36
37
37
This can be useful if you have a unit test that mocks API calls and you need to
38
38
wait for your mock promises to all resolve .
39
39
40
- The default ` callback ` is a no -op function (used like ` await wait() ` ). This can
41
- be helpful if you only need to wait for one tick of the event loop (in the case
42
- of mocked API calls with promises that resolve immediately ).
43
-
44
- The default ` timeout ` is ` 4500ms ` which will keep you under
45
- [Jest ' s default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
40
+ The default ` container ` is the global ` document ` . Make sure the elements you
41
+ wait for are descendants of ` container ` .
46
42
47
43
The default ` interval ` is ` 50ms ` . However it will run your callback immediately
48
- on the next tick of the event loop (in a ` setTimeout ` ) before starting the
49
- intervals .
44
+ before starting the intervals .
45
+
46
+ The default ` timeout ` is ` 1000ms ` which will keep you under
47
+ [Jest ' s default timeout of `5000ms`](https://jestjs.io/docs/en/jest-object.html#jestsettimeouttimeout).
48
+
49
+ < a name = " mutationobserveroptions" > </a >The default ` mutationObserverOptions ` is
50
+ ` {subtree: true, childList: true, attributes: true, characterData: true} ` which
51
+ will detect additions and removals of child elements (including text nodes ) in
52
+ the ` container ` and any of its descendants . It will also detect attribute
53
+ changes . When any of those changes occur , it will re - run the callback .
50
54
51
- ## ` waitForElement `
55
+ ## ` waitForElementToBeRemoved `
52
56
53
57
` ` ` typescript
54
- function waitForElement <T>(
55
- callback: () => T,
58
+ function waitForElementToBeRemoved <T>(
59
+ callback: (( ) => T) | T,
56
60
options?: {
57
61
container?: HTMLElement
58
62
timeout?: number
63
+ interval?: number
59
64
mutationObserverOptions?: MutationObserverInit
60
65
}
61
66
): Promise<T>
62
67
` ` `
63
68
64
- When in need to wait for DOM elements to appear , disappear , or change you can
65
- use ` waitForElement ` . The ` waitForElement ` function is a small wrapper around
66
- the
67
- [` MutationObserver ` ](https : // developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
69
+ To wait for the removal of element (s ) from the DOM you can use
70
+ ` waitForElementToBeRemoved ` . The ` waitForElementToBeRemoved ` function is a small
71
+ wrapper around the `wait` utility.
68
72
69
- Here ' s a simple example:
73
+ The first argument must be an element, array of elements, or a callback which returns
74
+ an element or array of elements.
75
+
76
+ Here is an example where the promise resolves with `true` because the element is
77
+ removed:
70
78
71
79
```javascript
72
- // ...
73
- // Wait until the callback does not throw an error and returns a truthy value. In this case, that means
74
- // it'll wait until we can get a form control with a label that matches "username".
75
- // The difference from ` wait ` is that rather than running your callback on
76
- // an interval, it's run as soon as there are DOM changes in the container
77
- // and returns the value returned by the callback.
78
- const usernameElement = await waitForElement(
79
- () => getByLabelText(container, 'username'),
80
- { container }
81
- )
82
- usernameElement.value = 'chucknorris'
83
- // ...
84
- ` ` `
80
+ const el = document.querySelector(' div.getOuttaHere' )
85
81
86
- You can also wait for multiple elements at once :
82
+ waitForElementToBeRemoved(document.querySelector(' div.getOuttaHere' ))
83
+ .then(() => console .log (' Element no longer in DOM' ))
87
84
88
- ` ` ` javascript
89
- const [usernameElement, passwordElement] = await waitForElement(
90
- () => [
91
- getByLabelText(container, 'username'),
92
- getByLabelText(container, 'password'),
93
- ],
94
- { container }
95
- )
85
+ el.setAttribute(' data-neat' , true )
86
+ // other mutations are ignored...
87
+
88
+ el.parentElement.removeChild(el )
89
+ // logs 'Element no longer in DOM'
96
90
```
97
91
98
- Using
99
- [` MutationObserver ` ](https : // developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
100
- is more efficient than polling the DOM at regular intervals with ` wait ` . This
101
- library sets up a
102
- [` 'mutationobserver-shim' ` ](https : // github.com/megawac/MutationObserver.js) on
103
- the global ` window ` object for cross -platform compatibility with older browsers
104
- and the [` jsdom ` ](https : // github.com/jsdom/jsdom/issues/639) that is usually
105
- used in Node -based tests .
92
+ `waitForElementToBeRemoved` will throw an error if the first argument is `null`
93
+ or an empty array:
106
94
107
- The default ` container ` is the global ` document ` . Make sure the elements you
108
- wait for will be attached to it , or set a different ` container ` .
95
+ ```javascript
96
+ waitForElementToBeRemoved(null ).catch(err = > console .log (err ))
97
+ waitForElementToBeRemoved(queryByText (/not here /i )).catch(err = > console .log (err ))
98
+ waitForElementToBeRemoved(queryAllByText (/not here /i )).catch(err = > console .log (err ))
99
+ waitForElementToBeRemoved(() => getByText (/not here /i )).catch(err = > console .log (err ))
109
100
110
- The default ` timeout ` is ` 4500ms ` which will keep you under
111
- [ Jest ' s default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout) .
101
+ // Error: The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.
102
+ ```
112
103
113
- <a name = " mutationobserveroptions" > </a >The default ` mutationObserverOptions ` is
114
- ` {subtree: true, childList: true, attributes: true, characterData: true} ` which
115
- will detect additions and removals of child elements (including text nodes ) in
116
- the ` container ` and any of its descendants . It will also detect attribute
117
- changes .
104
+ The options object is forwarded to `wait`.
118
105
119
- ## ` waitForDomChange `
106
+ ## `waitForDomChange` ( DEPRECATED , use wait instead )
120
107
121
108
```typescript
122
109
function waitForDomChange<T >(options ? : {
@@ -167,31 +154,23 @@ container.setAttribute('data-cool', 'false')
167
154
*/
168
155
` ` `
169
156
170
- Using
171
- [` MutationObserver ` ](https :// developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
172
- is more efficient than polling the DOM at regular intervals with ` wait ` . This
173
- library sets up a
174
- [` 'mutationobserver-shim' ` ](https :// github.com/megawac/MutationObserver.js) on
175
- the global ` window ` object for cross -platform compatibility with older browsers
176
- and the [` jsdom ` ](https :// github.com/jsdom/jsdom/issues/639) that is usually
177
- used in Node -based tests .
178
-
179
157
The default ` container ` is the global ` document ` . Make sure the elements you
180
- wait for will be attached to it , or set a different ` container ` .
158
+ wait for are descendants of ` container ` .
181
159
182
- The default ` timeout ` is ` 4500ms ` which will keep you under
183
- [Jest ' s default timeout of `5000ms`](https://facebook.github.io/jest /docs/en/jest-object.html#jestsettimeouttimeout).
160
+ The default ` timeout ` is ` 1000ms ` which will keep you under
161
+ [Jest ' s default timeout of `5000ms`](https://jestjs.io /docs/en/jest-object.html#jestsettimeouttimeout).
184
162
185
163
<a name = " mutationobserveroptions" ></a >The default ` mutationObserverOptions ` is
186
164
` {subtree: true, childList: true, attributes: true, characterData: true} ` which
187
165
will detect additions and removals of child elements (including text nodes ) in
188
166
the ` container ` and any of its descendants . It will also detect attribute
189
167
changes .
190
168
191
- ## ` waitForElementToBeRemoved `
169
+
170
+ ## ` waitForElement ` (DEPRECATED , use ` find* ` queries or ` wait ` )
192
171
193
172
` ` ` typescript
194
- function waitForElementToBeRemoved <T>(
173
+ function waitForElement <T>(
195
174
callback: () => T,
196
175
options?: {
197
176
container?: HTMLElement
@@ -201,54 +180,42 @@ function waitForElementToBeRemoved<T>(
201
180
): Promise<T>
202
181
` ` `
203
182
204
- To wait for the removal of element ( s ) from the DOM you can use
205
- ` waitForElementToBeRemoved ` . The ` waitForElementToBeRemoved ` function is a small
206
- wrapper around the
183
+ When in need to wait for DOM elements to appear , disappear , or change you can
184
+ use ` waitForElement ` . The ` waitForElement ` function is a small wrapper around
185
+ the
207
186
[` MutationObserver ` ](https : // developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
208
187
209
- The callback must return the pre -existing element or array of elements that are
210
- expected to be removed .
211
-
212
- Here is an example where the promise resolves with ` true ` because the element is
213
- removed :
188
+ Here ' s a simple example:
214
189
215
190
` ` ` javascript
216
- const el = document.querySelector('div.getOuttaHere')
217
-
218
- waitForElementToBeRemoved(() =>
219
- document.querySelector('div.getOuttaHere')
220
- ).then(() => console.log('Element no longer in DOM'))
221
-
222
- el.setAttribute('data-neat', true)
223
- // other mutations are ignored...
224
-
225
- el.parentElement.removeChild(el)
226
- // logs 'Element no longer in DOM'
191
+ // ...
192
+ // Wait until the callback does not throw an error and returns a truthy value. In this case, that means
193
+ // it'll wait until we can get a form control with a label that matches "username".
194
+ // The difference from ` wait ` is that rather than running your callback on
195
+ // an interval, it's run as soon as there are DOM changes in the container
196
+ // and returns the value returned by the callback.
197
+ const usernameElement = await waitForElement(
198
+ () => getByLabelText(container, 'username'),
199
+ { container }
200
+ )
201
+ usernameElement.value = 'chucknorris'
202
+ // ...
227
203
` ` `
228
204
229
- ` waitForElementToBeRemoved ` will throw an error when the provided callback does
230
- not return an element .
205
+ You can also wait for multiple elements at once :
231
206
232
207
` ` ` javascript
233
- waitForElementToBeRemoved(() => null).catch(err => console.log(err))
234
-
235
- // 'The callback function which was passed did not return an element
236
- // or non-empty array of elements.
237
- // waitForElementToBeRemoved requires that the element(s) exist
238
- // before waiting for removal.'
208
+ const [usernameElement, passwordElement] = await waitForElement(
209
+ () => [
210
+ getByLabelText(container, 'username'),
211
+ getByLabelText(container, 'password'),
212
+ ],
213
+ { container }
214
+ )
239
215
` ` `
240
216
241
- Using
242
- [` MutationObserver ` ](https :// developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
243
- is more efficient than polling the DOM at regular intervals with ` wait ` . This
244
- library sets up a
245
- [` 'mutationobserver-shim' ` ](https :// github.com/megawac/MutationObserver.js) on
246
- the global ` window ` object for cross -platform compatibility with older browsers
247
- and the [` jsdom ` ](https :// github.com/jsdom/jsdom/issues/639) that is usually
248
- used in Node -based tests .
249
-
250
217
The default ` container ` is the global ` document ` . Make sure the elements you
251
- wait for are descendants of ` container ` .
218
+ wait for will be attached to it , or set a different ` container ` .
252
219
253
220
The default ` timeout ` is ` 4500ms ` which will keep you under
254
221
[Jest ' s default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
0 commit comments