-
Notifications
You must be signed in to change notification settings - Fork 669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add async guide #282
Merged
Merged
Add async guide #282
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
b16c3c2
Add new guide page
lmiller1990 c9180e1
Add a bit more
lmiller1990 9e64bcb
Upadte
lmiller1990 0d2959e
Add more explanation
lmiller1990 b600b8a
Add examples
lmiller1990 1a31d96
Foratting
lmiller1990 309aebc
Foramtting
lmiller1990 34c8a38
Remove watcher section
lmiller1990 d675067
Spacing
lmiller1990 7b88e8a
Make improvements using feedback
lmiller1990 cc8aa0a
Fix type and reword flush-promises explanation
lmiller1990 46d7265
Change from @click to v-on:click
lmiller1990 cc47f9f
Fix linting error
lmiller1990 85e97e3
updates -> DOM updates, Jest and Karma -> Jest and Mocha
lmiller1990 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Testing Asynchronous Behavior | ||
|
||
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. | ||
|
||
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://facebook.github.io/jest/docs/en/manual-mocks.html#content). | ||
|
||
The implementation of the `axios` mock looks like this: | ||
|
||
``` js | ||
export default { | ||
get: () => new Promise(resolve => { | ||
resolve({ data: 'value' }) | ||
}) | ||
} | ||
``` | ||
|
||
The below component makes an API call when a button is clicked, then assigns the response to `value`. | ||
|
||
``` html | ||
<template> | ||
<button @click="fetchResults" /> | ||
</template> | ||
|
||
<script> | ||
import axios from 'axios' | ||
|
||
export default { | ||
data () { | ||
return { | ||
value: null | ||
} | ||
}, | ||
|
||
methods: { | ||
async fetchResults () { | ||
const response = await axios.get('mock/service') | ||
this.value = response.data | ||
} | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
A test can be written like this: | ||
|
||
``` js | ||
import { shallow } from 'vue-test-utils' | ||
import Foo from './Foo' | ||
jest.mock('axios') | ||
|
||
test('Foo', () => { | ||
it('fetches async when a button is clicked', () => { | ||
const wrapper = shallow(Foo) | ||
wrapper.find('button').trigger('click') | ||
expect(wrapper.vm.value).toEqual('value') | ||
}) | ||
}) | ||
``` | ||
|
||
This test currently fails because the assertion is called before the promise in `fetchResults` resolves. Most unit test libraries provide a callback to let the runner know when the test is complete. Jest and Mocha both use `done`. We can use `done` in combination with `$nextTick` or `setTimeout` to ensure any promises resolve before the assertion is made. | ||
|
||
``` js | ||
test('Foo', () => { | ||
it('fetches async when a button is clicked', (done) => { | ||
const wrapper = shallow(Foo) | ||
wrapper.find('button').trigger('click') | ||
wrapper.vm.$nextTick(() => { | ||
expect(wrapper.vm.value).toEqual('value') | ||
done() | ||
}) | ||
}) | ||
}) | ||
``` | ||
|
||
The reason `$nextTick` or `setTimeout` allow the test to pass is because the microtask queue where promise callbacks are processed run before the task queue, where `$nextTick` and `setTimeout` are processed. This means by the time the `$nexTick` and `setTimeout` run, any promise callbacks on the microtask queue will have been executed. See [here](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) for a more detailed explanation. | ||
|
||
Another solution is to use an `async` function and the npm package `flush-promises`. `flush-promises` flushes all pending resolved promise handlers. You can `await` the call of `flushPromises` to flush pending promises and improve the readability of your test. | ||
|
||
The updated test looks like this: | ||
|
||
``` js | ||
import { shallow } from 'vue-test-utils' | ||
import flushPromises from 'flush-promises' | ||
import Foo from './Foo' | ||
jest.mock('axios') | ||
|
||
test('Foo', () => { | ||
it('fetches async when a button is clicked', async () => { | ||
const wrapper = shallow(Foo) | ||
wrapper.find('button').trigger('click') | ||
await flushPromises() | ||
expect(wrapper.vm.value).toEqual('value') | ||
}) | ||
}) | ||
``` | ||
|
||
This same technique can be applied to Vuex actions, which return a promise by default. | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a line break after the import statement