Skip to content

Commit b05c9d0

Browse files
eddyerburghkazupon
authored andcommitted
Add guide on next tick (#1156)
* docs: update getting started * docs: update common tips * docs: update testing-async-components * docs: remove details on sync updating * Update testin-async-components * docs: update common-tips section * docs: reword getting-started * docs: reword * docs: update getting-started * docs: reword * docs: reword * docs: update example
1 parent 3bf5912 commit b05c9d0

File tree

4 files changed

+70
-11
lines changed

4 files changed

+70
-11
lines changed

docs/guides/common-tips.md

+24
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ const wrapper = shallowMount(Component)
2727
wrapper.vm // the mounted Vue instance
2828
```
2929

30+
### Using `nextTick`
31+
32+
Vue batches watcher updates and runs them asynchronously on the "next tick".
33+
34+
In practice, this means you must wait for updates to run after you set a reactive property. You can wait for updates with `Vue.nextTick()`:
35+
36+
```js
37+
it('updates text', async () => {
38+
const wrapper = mount(Component)
39+
wrapper.trigger('click')
40+
await Vue.nextTick()
41+
expect(wrapper.text()).toContain('updated')
42+
})
43+
```
44+
45+
The following methods often cause watcher updates that require you to wait for the next tick:
46+
47+
- `setChecked`
48+
- `setData`
49+
- `setSelected`
50+
- `setProps`
51+
- `setValue`
52+
- `trigger`
53+
3054
### Asserting Emitted Events
3155

3256
Each mounted wrapper automatically records all events emitted by the underlying Vue instance. You can retrieve the recorded events using the `wrapper.emitted()` method:

docs/guides/dom-events.md

-4
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,3 @@ A key name after the dot `keydown.up` is translated to a `keyCode`. This is supp
207207
| home | 36 |
208208
| pageup | 33 |
209209
| pagedown | 34 |
210-
211-
### Important
212-
213-
Vue Test Utils triggers event synchronously. Consequently, `Vue.nextTick` is not required.

docs/guides/getting-started.md

+19-5
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,29 @@ it('button click should increment the count', () => {
102102
})
103103
```
104104

105-
### What about `nextTick`?
105+
In order to test that the counter text has updated, we need to learn about `nextTick`.
106106

107-
Vue batches pending DOM updates and applies them asynchronously to prevent unnecessary re-renders caused by multiple data mutations. This is why in practice we often have to use `Vue.nextTick` to wait until Vue has performed the actual DOM update after we trigger some state change.
107+
### Using `nextTick`
108108

109-
To simplify usage, Vue Test Utils applies all updates synchronously so you don't need to use `Vue.nextTick` to wait for DOM updates in your tests.
109+
Vue batches pending DOM updates and applies them asynchronously to prevent unnecessary re-renders caused by multiple data mutations.
110110

111-
_Note: `nextTick` is still necessary when you need to explictly advance the event loop, for operations such as asynchronous callbacks or promise resolution._
111+
_You can read more about asynchronous updates in the [Vue docs](https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue)_
112112

113-
If you do still need to use `nextTick` in your test files, be aware that any errors thrown inside it may not be caught by your test runner as it uses promises internally. There are two approaches to fixing this: either you can set the `done` callback as Vue's global error handler at the start of the test, or you can call `nextTick` without an argument and return it as a promise:
113+
We need to use `Vue.nextTick()` to wait until Vue has performed the DOM update after we set a reactive property. In the counter example, setting the `count` property schedules a DOM update to run on the next tick.
114+
115+
We can `await` `Vue.nextTick()` by writing the tests in an async function:
116+
117+
```js
118+
it('button click should increment the count text', async () => {
119+
expect(wrapper.text()).toContain('0')
120+
const button = wrapper.find('button')
121+
button.trigger('click')
122+
await Vue.nextTick()
123+
expect(wrapper.text()).toContain('1')
124+
})
125+
```
126+
127+
When you use `nextTick` in your test files, be aware that any errors thrown inside it may not be caught by your test runner as it uses promises internally. There are two approaches to fixing this: either you can set the `done` callback as Vue's global error handler at the start of the test, or you can call `nextTick` without an argument and return it as a promise:
114128

115129
```js
116130
// this will not be caught

docs/guides/testing-async-components.md

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
11
## Testing Asynchronous Behavior
22

3-
To simplify testing, Vue Test Utils applies DOM updates _synchronously_. However, there are some techniques you need to be aware of when testing a component with asynchronous behavior such as callbacks or promises.
3+
There are two types of asynchronous behavior you will encounter in your tests:
44

5-
One of the most common asynchronous behaviors is API calls and Vuex actions. The following examples shows how to test a method that makes an API call. This example uses Jest to run the test and to mock the HTTP library `axios`. More about Jest manual mocks can be found [here](https://jestjs.io/docs/en/manual-mocks#content).
5+
1. Updates applied by Vue
6+
2. Asynchronous behavior outside of Vue
7+
8+
## Updates applied by Vue
9+
10+
Vue batches pending DOM updates and applies them asynchronously to prevent unnecessary re-renders caused by multiple data mutations.
11+
12+
_You can read more about asynchronous updates in the [Vue docs](https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue)_
13+
14+
In practice, this means you have to use `Vue.nextTick()` to wait until Vue has performed updates after you set a reactive property.
15+
16+
The easiest way to use `Vue.nextTick()` is to write your tests in an async function:
17+
18+
```js
19+
it('button click should increment the count text', async () => {
20+
expect(wrapper.text()).toContain('0')
21+
const button = wrapper.find('button')
22+
button.trigger('click')
23+
await Vue.nextTick()
24+
expect(wrapper.text()).toContain('1')
25+
})
26+
```
27+
28+
## Asynchronous behavior outside of Vue
29+
30+
One of the most common asynchronous behaviors outside of Vue is API calls in Vuex actions. The following examples shows how to test a method that makes an API call. This example uses Jest to run the test and to mock the HTTP library `axios`. More about Jest manual mocks can be found [here](https://jestjs.io/docs/en/manual-mocks.html#content).
631

732
The implementation of the `axios` mock looks like this:
833

0 commit comments

Comments
 (0)