Skip to content

Commit ef6f166

Browse files
authored
Revamp Getting Started (vuejs#1613)
* docs: add VTL * docs: reduce prominence of shallow mounting * docs: fix headings * docs: update Getting Started according to vtu-2 docs * docs: remove importance of shallow mount * docs: fix propsdata
1 parent ed070d7 commit ef6f166

File tree

4 files changed

+59
-117
lines changed

4 files changed

+59
-117
lines changed

Diff for: docs/guides/common-tips.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,29 @@ For UI components, we don't recommend aiming for complete line-based coverage, b
66

77
Instead, we recommend writing tests that assert your component's public interface, and treat its internals as a black box. A single test case would assert that some input (user interaction or change of props) provided to the component results in the expected output (render result or emitted custom events).
88

9-
For example, for the `Counter` component which increments a display counter by 1 each time a button is clicked, its test case would simulate the click and assert that the rendered output has increased by 1. The test doesn't care about how the `Counter` increments the value, it only cares about the input and the output.
9+
For example, imagine a `Counter` component which increments a display counter by 1 each time a button is clicked. Its test case would simulate the click and assert that the rendered output has increased by 1. The test should not care about how the `Counter` increments the value – it only cares about the input and the output.
1010

1111
The benefit of this approach is that as long as your component's public interface remains the same, your tests will pass no matter how the component's internal implementation changes over time.
1212

1313
This topic is discussed with more details in a [great presentation by Matt O'Connell](https://www.youtube.com/watch?v=OIpfWTThrK8).
1414

15-
### Shallow Rendering
15+
### Shallow mounting
1616

17-
In unit tests, we typically want to focus on the component being tested as an isolated unit and avoid indirectly asserting the behavior of its child components.
17+
Sometimes, mounting a whole component with all its all dependencies might become slow or cumbersome. For example, components that contain many child components.
1818

19-
In addition, for components that contain many child components, the entire rendered tree can get really big. Repeatedly rendering all child components could slow down our tests.
20-
21-
Vue Test Utils allows you to mount a component without rendering its child components (by stubbing them) with the `shallowMount` method:
19+
Vue Test Utils allows you to mount a component without rendering its child components (by stubbing them) with the [`shallowMount`](../api/#shallowmount) method.
2220

2321
```js
2422
import { shallowMount } from '@vue/test-utils'
23+
import Component from '../Component.vue'
2524

2625
const wrapper = shallowMount(Component)
27-
wrapper.vm // the mounted Vue instance
2826
```
2927

28+
Like [mount](../api/#mount), it creates a [Wrapper](../api/wrapper) that contains the mounted and rendered Vue component, but with stubbed child components.
29+
30+
Notice that using `shallowMount` will make the component under testing different from the component you run in your application – some of its parts won't be rendered! This is why it is not the suggested way of testing components unless you face performance issues or need to simplify test arrangements.
31+
3032
### Lifecycle Hooks
3133

3234
<div class="vueschool" style="margin-top:1em;"><a href="https://vueschool.io/lessons/learn-how-to-test-vuejs-lifecycle-methods?friend=vuejs" target="_blank" rel="sponsored noopener" title="Learn how to use Vue Test Utils to test Vue.js Lifecycle Hooks with Vue School">Learn how to test lifecycle methods and intervals with Vue School</a></div>

Diff for: docs/guides/getting-started.md

+42-108
Original file line numberDiff line numberDiff line change
@@ -2,141 +2,75 @@
22

33
<div class="vueschool"><a href="https://vueschool.io/lessons/installing-vue-test-utils?friend=vuejs" target="_blank" rel="sponsored noopener" title="Learn how to get started with Vue Test Utils, Jest, and testing Vue Components with Vue School">Learn how to get started with Vue Test Utils, Jest, and testing Vue Components</a></div>
44

5-
### Setup
5+
### What is Vue Test Utils?
66

7-
If you already have a project that was created with the [Vue CLI](https://cli.vuejs.org/), you might want to add and configure the [core Jest plugin](https://cli.vuejs.org/core-plugins/unit-jest.html) or the [core Mocha plugin](https://cli.vuejs.org/core-plugins/unit-mocha.html).
7+
Vue Test Utils (VTU) is a set of utility functions aimed to simplify testing Vue.js components. It provides some methods to **mount** and **interact** with Vue components in an isolated manner.
88

9-
If needed, check out the [Installation guides](../installation/README.md) for further details.
10-
11-
### Mounting Components
12-
13-
Vue Test Utils tests Vue components by mounting them in isolation, mocking the necessary inputs (props, injections and user events) and asserting the outputs (render result, emitted custom events).
14-
15-
Mounted components are returned inside a [Wrapper](../api/wrapper/), which exposes many convenience methods for manipulating, traversing and querying the underlying Vue component instance.
16-
17-
You can create wrappers using the `mount` method. Let's create a file called `test.js`:
9+
Let's see an example:
1810

1911
```js
20-
// test.js
21-
22-
// Import the `mount()` method from the test utils
23-
// and the component you want to test
12+
// Import the `mount()` method from Vue Test Utils
2413
import { mount } from '@vue/test-utils'
25-
import Counter from './counter'
26-
27-
// Now mount the component and you have the wrapper
28-
const wrapper = mount(Counter)
29-
30-
// You can access the actual Vue instance via `wrapper.vm`
31-
const vm = wrapper.vm
32-
33-
// To inspect the wrapper deeper just log it to the console
34-
// and your adventure with the Vue Test Utils begins
35-
console.log(wrapper)
36-
```
37-
38-
### Test rendered HTML output of the component
39-
40-
Now that we have the wrapper, the first thing we can do is to verify that the rendered HTML output of the component matches what is expected.
4114

42-
```js
43-
import { mount } from '@vue/test-utils'
44-
import Counter from './counter'
45-
46-
describe('Counter', () => {
47-
// Now mount the component and you have the wrapper
48-
const wrapper = mount(Counter)
49-
50-
it('renders the correct markup', () => {
51-
expect(wrapper.html()).toContain('<span class="count">0</span>')
15+
// The component to test
16+
const MessageComponent = {
17+
template: '<p>{{ msg }}</p>',
18+
props: ['msg']
19+
}
20+
21+
test('displays message', () => {
22+
// mount() returns a wrapped Vue component we can interact with
23+
const wrapper = mount(MessageComponent, {
24+
propsData: {
25+
msg: 'Hello world'
26+
}
5227
})
5328

54-
// it's also easy to check for the existence of elements
55-
it('has a button', () => {
56-
expect(wrapper.contains('button')).toBe(true)
57-
})
29+
// Assert the rendered text of the component
30+
expect(wrapper.text()).toContain('Hello world')
5831
})
5932
```
6033

61-
Now run the tests with `npm test`. You should see the tests passing.
34+
Mounted components are returned inside a [Wrapper](../api/wrapper/), which exposes methods for querying and interacting with the component under testing.
6235

6336
### Simulating User Interaction
6437

65-
Our counter should increment the count when the user clicks the button. To simulate the behavior, we need to first locate the button with `wrapper.find()`, which returns a **wrapper for the button element**. We can then simulate the click by calling `.trigger()` on the button wrapper:
38+
Let's imagine a counter component that increments when user clicks the button:
6639

6740
```js
68-
it('button click should increment the count', () => {
69-
expect(wrapper.vm.count).toBe(0)
70-
const button = wrapper.find('button')
71-
button.trigger('click')
72-
expect(wrapper.vm.count).toBe(1)
73-
})
41+
const Counter = {
42+
template: `
43+
<div>
44+
<button @click="count++">Add up</button>
45+
<p>Total clicks: {{ count }}</p>
46+
</div>
47+
`,
48+
data() {
49+
return { count: 0 }
50+
}
51+
}
7452
```
7553

76-
In order to test that the counter text has updated, we need to learn about `nextTick`.
77-
78-
### Using `nextTick` and awaiting actions
79-
80-
Anytime you make a change (in computed, data, vuex state, etc) which updates the DOM (ex. show a component from v-if or display dynamic text), you should await the `nextTick` function before running the assertion.
81-
This is because Vue batches pending DOM updates and _applies them asynchronously_ to prevent unnecessary re-renders caused by multiple data mutations.
82-
83-
_You can read more about asynchronous updates in the [Vue docs](https://vuejs.org/v2/guide/reactivity.html#Async-Update-Queue)_
84-
85-
After updating a reactive property we can await methods like `trigger` or `wrapper.vm.$nextTick` directly, until Vue has performed the DOM update. In the counter example, setting the `count` property schedules a DOM update to run on the next tick.
86-
87-
Lets see how we can `await trigger()` by writing the tests in an async function:
54+
To simulate the behavior, we need to first locate the button with `wrapper.find()`, which returns a **wrapper for the button element**. We can then simulate the click by calling `.trigger()` on the button wrapper:
8855

8956
```js
90-
it('button click should increment the count text', async () => {
91-
expect(wrapper.text()).toContain('0')
57+
test('increments counter value on click', async () => {
58+
const wrapper = mount(Counter)
9259
const button = wrapper.find('button')
93-
await button.trigger('click')
94-
expect(wrapper.text()).toContain('1')
95-
})
96-
```
97-
98-
`trigger` returns a promise, which can be awaited as seen above or chained with `then` like a regular promise callback. Methods like `trigger` just return `Vue.nextTick` internally.
99-
You can read more in depth about [Testing Asynchronous Components](../guides/README.md#testing-async-components).
100-
101-
If for some reason you choose to use `nextTick` instead 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:
102-
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:
103-
104-
```js
105-
// errors will not be caught
106-
it('will time out', done => {
107-
Vue.nextTick(() => {
108-
expect(true).toBe(false)
109-
done()
110-
})
111-
})
60+
const text = wrapper.find('p')
11261

113-
// the three following tests will work as expected
114-
it('will catch the error using done', done => {
115-
Vue.config.errorHandler = done
116-
Vue.nextTick(() => {
117-
expect(true).toBe(false)
118-
done()
119-
})
120-
})
62+
expect(text.text()).toContain('Total clicks: 0')
12163

122-
it('will catch the error using a promise', () => {
123-
return Vue.nextTick().then(function() {
124-
expect(true).toBe(false)
125-
})
126-
})
64+
await button.trigger('click')
12765

128-
it('will catch the error using async/await', async () => {
129-
await Vue.nextTick()
130-
expect(true).toBe(false)
66+
expect(text.text()).toContain('Total clicks: 1')
13167
})
13268
```
13369

134-
`Vue.nextTick` is equal to `component.vm.$nextTick`, where `component` can be the result of `mount` or `find`.
135-
136-
As mentioned in the beginning, in most cases, awaiting `trigger` is the recommended way to go.
70+
Notice how the test must be `async` and that `trigger` needs to be awaited. Check out the [Testing Asynchronous Behavior](./README.md#testing-asynchronous-behavior) guide to understand why this is needed and other things to consider when testing asynchronous scenarios.
13771

13872
### What's Next
13973

140-
- Learn more about [common techniques when writing tests](./README.md#knowing-what-to-test).
141-
- Integrate Vue Test Utils into your project by [choosing a test runner](./README.md#choosing-a-test-runner).
142-
- Learn more about [Testing Asynchronous Behavior](./README.md#testing-asynchronous-behavior)
74+
Check out our [common tips when writing tests](./README.md#knowing-what-to-test).
75+
76+
Alternatively, you can explore the [full API](../api/).

Diff for: docs/guides/testing-async-components.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ There are two types of asynchronous behavior you will encounter in your tests:
55
1. Updates applied by Vue
66
2. Asynchronous behavior outside of Vue
77

8-
## Updates applied by Vue
8+
### Updates applied by Vue
99

1010
Vue batches pending DOM updates and applies them asynchronously to prevent unnecessary re-renders caused by multiple data mutations.
1111

@@ -45,7 +45,7 @@ Methods that can be awaited are:
4545
- [setProps](../api/wrapper/README.md#setprops)
4646
- [trigger](../api/wrapper/README.md#trigger)
4747

48-
## Asynchronous behavior outside of Vue
48+
### Asynchronous behavior outside of Vue
4949

5050
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).
5151

Diff for: docs/guides/useful-libraries-for-testing.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Vue Test Utils provides useful methods for testing Vue components. Community members have also written some additional libraries which either extend `vue-test-utils` with extra useful methods, or provide tools for testing other things found in Vue applications.
44

5+
### Vue Testing Library
6+
7+
[Vue Testing Library](https://github.com/testing-library/vue-testing-library) is a set of tools focused on testing components without relying on implementation details. Built with accessibility in mind, its approach also makes refactoring a breeze.
8+
9+
It is built on top of Vue Test Utils.
10+
511
### `vuex-mock-store`
612

713
[`vuex-mock-store`](https://github.com/posva/vuex-mock-store) provides a simple and straightforward mock store to simplify testing components consuming a Vuex store.

0 commit comments

Comments
 (0)