Skip to content

Commit c470a27

Browse files
authored
Merge pull request #36 from vuejs/feedback
Feedback
2 parents 025ff2f + 8a70d6b commit c470a27

File tree

4 files changed

+252
-139
lines changed

4 files changed

+252
-139
lines changed

src/guide/conditional-rendering.md

+22-8
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,46 @@ In the `<Nav>` component, a link to the user's profile is shown. In addition, if
3030

3131
## Using `get()`
3232

33-
`wrapper` has a `get()` method for asserting an element exists. It uses [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) syntax. We can assert the profile link is present using `get()`:
33+
`wrapper` has a `get()` method that searches for an existing element. It uses [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) syntax.
34+
35+
We can assert the profile link content by using `get()`:
3436

3537
```js
3638
test('renders a profile link', () => {
3739
const wrapper = mount(Nav)
38-
wrapper.get('#profile')
40+
41+
// Here we are implicitly asserting that the
42+
// element #profile exists.
43+
const profileLink = wrapper.get('#profile')
44+
45+
expect(profileLink.text()).toEqual('My Profile')
3946
})
4047
```
4148

4249
If `get()` does not return an element matching the selector, it will raise an error, and your test will fail.
4350

4451
## Using `find()` and `exists()`
4552

46-
`get()` works for asserting elements do exist, because it throws an error when it can't find an element, you can't use it to assert elements don't exist. For this, we can use `find()` and `exists()`. The next test asserts that if `admin` is `false` (which is it by default), the admin link is not present:
53+
`get()` works for asserting elements do exist. However, as we mentioned, it throws an error when it can't find an element, so you can't use it to assert whether if elements exist.
54+
55+
To do so, we use `find()` and `exists()`. The next test asserts that if `admin` is `false` (which is it by default), the admin link is not present:
4756

4857
```js
4958
test('does not render an admin link', () => {
5059
const wrapper = mount(Nav)
51-
const adminLink = wrapper.find('#admin')
52-
expect(adminLink.exists()).toBe(false)
60+
61+
// Using `wrapper.get` would throw and make the test fail.
62+
expect(wrapper.find('#admin').exists()).toBe(false)
5363
})
5464
```
5565

5666
Notice we are calling `exists()` on the value returned from `.find()`? `find()`, like `mount()`, also returns a wrapper, similar to `mount()`. `mount()` has a few extra methods, because it's wrapping a Vue component, and `find()` only returns a regular DOM node, but many of the methods are shared between both. Some other methods include `classes()`, which gets the classes a DOM node has, and `trigger()` for simulating user interaction. You can find a list of methods supported [here](/api/#wrapper-methods).
5767

5868
## Using `data`
5969

60-
The final test is to assert that the admin link is rendered when `admin` is `true`. It's default by `false`, but we can override that using the second argument to `mount()`, the [`mounting options`](/api/#mount-options). For `data`, we use the aptly named `data` option:
70+
The final test is to assert that the admin link is rendered when `admin` is `true`. It's `false` by default, but we can override that using the second argument to `mount()`, the [`mounting options`](/api/#mount-options).
71+
72+
For `data`, we use the aptly named `data` option:
6173

6274
```js
6375
test('renders an admin link', () => {
@@ -68,8 +80,10 @@ test('renders an admin link', () => {
6880
}
6981
}
7082
})
71-
const adminLink = wrapper.find('#admin')
72-
expect(adminLink.exists()).toBe(true)
83+
84+
// Again, by using `get()` we are implicitly asserting that
85+
// the element exists.
86+
expect(wrapper.get('#admin').text()).toEqual('Admin')
7387
})
7488
```
7589

src/guide/event-handling.md

+89-49
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ Vue components interact with each other via props and by emitting events by call
44

55
## The Counter component
66

7-
Here is a simple `<Counter>` component. It has a button that increments a `count` property when it is clicked. It also emits an `increment` event with the latest value of `count` by calling `this.$emit('increment', this.count)`:
7+
Here is a simple `<Counter>` component. It features a button that, when clicked, increments an internal count variable and emits its value:
88

99
```js
1010
const Counter = {
11-
template: `
12-
<button @click="handleClick">Increment</button>
13-
<div>Count: {{ count }}</div>
14-
`,
11+
template: '<button @click="handleClick">Increment</button>',
1512
data() {
1613
return {
1714
count: 0
@@ -26,84 +23,127 @@ const Counter = {
2623
}
2724
```
2825

29-
To fully test this component, we should verify that when the button is clicked, the `count` shown in the template is updated. We can also verify that an `increment` event with the latest `count` value is emitted. We will start with the latter.
26+
To fully test this component, we should verify that an `increment` event with the latest `count` value is emitted.
3027

31-
## `VueWrapper.emitted()`
28+
## Asserting the emitted events
3229

33-
`VueWrapper` has an `emitted()` method. It returns an object with all the events the component has emitted, and their arguments in an array. Let's see how it works:
30+
To do so, we will rely on the `emitted()` method. It **returns an object with all the events the component has emitted**, and their arguments in an array. Let's see how it works:
3431

3532
```js
36-
test('emits and event with count when clicked', () => {
33+
test('emits an event when clicked', () => {
3734
const wrapper = mount(Counter)
38-
wrapper.find('button').trigger('click')
35+
3936
wrapper.find('button').trigger('click')
4037
wrapper.find('button').trigger('click')
4138

42-
console.log(wrapper.emitted()) // { increment: [ [ 1 ], [ 2 ], [ 3 ] ] }
39+
expect(wrapper.emitted()).toHaveProperty('increment')
4340
})
4441
```
4542

46-
> If you haven't seen `trigger()` before, don't worry. It's used to simulate user interaction. You can learn more in [Forms](/guide/forms).
43+
> If you haven't seen `trigger()` before, don't worry. It's used to simulate user interaction. You can learn more in [Forms](/guide/forms).
4744
48-
The output of `emitted()` might be a little confusing at first. In this test, we are only interested in the `increment` event, so we can access that with `wrapper.emitted('increment')`. This would return `[ [ 1 ], [ 2 ], [ 3 ] ]`. Let's format it a bit more nicely to see what's going on:
45+
The first thing to notice is that `emitted()` returns an object, where each key matches an emitted event. In this case, `increment`.
4946

50-
```js
51-
// console.log(wrapper.emitted('increment'))
52-
[
53-
[ 1 ], // first time is it called, `count` is 1
54-
[ 2 ], // second time is it called, `count` is 2
55-
[ 3 ], // third time is it called, `count` is 3
56-
]
47+
This test should pass. We made sure we emitted an event with the appropriate name.
48+
49+
## Asserting the arguments of the event
50+
51+
This is good - but we can do better! We need to check that we emit the right arguments when `this.$emit('increment', this.count)` is called.
52+
53+
Our next step is to assert that the event contains the `count` value. We do so by passing an argument to `emitted()`.
54+
55+
```js {9}
56+
test('emits an event with count when clicked', () => {
57+
const wrapper = mount(Counter)
58+
59+
wrapper.find('button').trigger('click')
60+
wrapper.find('button').trigger('click')
61+
62+
// `emitted()` accepts an argument. It returns an array with all the
63+
// occurrences of `this.$emit('increment')`.
64+
const incrementEvent = wrapper.emitted('increment')
65+
66+
// We have "clicked" twice, so the array of `increment` should
67+
// have two values.
68+
expect(incrementEvent).toHaveLength(2)
69+
70+
// Assert the result of the first click.
71+
// Notice that the value is an array.
72+
expect(incrementEvent[0]).toEqual([1])
73+
74+
// Then, the result of the second one.
75+
expect(incrementEvent[1]).toEqual([2])
76+
})
5777
```
5878

59-
Each entry in the array represents one `increment` event that was emitted. Each entry in the array represents an argument to `this.$emit()`. For example, if the code was `this.$emit('increment, this.count, { status: 'success' })`, and the button was clicked twice, `emitted('increment')` would be:
79+
Let's recap and break down the output of `emitted()`. Each of these keys contains the different values emitted during the test:
6080

6181
```js
62-
[
63-
[ // first `increment` event
64-
1, // first argument
65-
{ status: 'success' } // second argument
66-
],
67-
[ // second `increment` event
68-
2, // first argument
69-
{ status: 'success' } // second argument
70-
]
82+
// console.log(wrapper.emitted('increment'))
83+
[
84+
[ 1 ], // first time it is called, `count` is 1
85+
[ 2 ], // second time it is called, `count` is 2
7186
]
7287
```
7388

74-
Each element in the array corresponds to an argument in `this.$emit`.
75-
76-
## Writing a Test
89+
## Asserting complex events
7790

78-
Now we know that `emitted('eventName')` captures the events, we can write a simple test to assert an `increment` event is emitted:
79-
80-
```js
81-
test('emits and event with count when clicked', () => {
82-
const wrapper = mount(Counter)
91+
Imagine that now our `<Counter>` component needs to emit an object with additional information. For instance, we need to tell any parent component listening to the `@increment` event if `count` is even or odd:
8392

84-
wrapper.find('button').trigger('click')
93+
```js {12-15}
94+
const Counter = {
95+
template: `<button @click="handleClick">Increment</button>`,
96+
data() {
97+
return {
98+
count: 0
99+
}
100+
},
101+
methods: {
102+
handleClick() {
103+
this.count += 1
85104

86-
expect(wrapper.emitted()).toHaveProperty('increment')
87-
})
105+
this.$emit('increment', {
106+
count: this.count,
107+
isEven: this.count % 2 === 0
108+
})
109+
}
110+
}
111+
}
88112
```
89113

90-
This is good - but we can do better. With the knowledge that `increment` will return an array, where each element represents an event and it's arguments, we can fully test the component by making assertions against the arguments passed when `this.$emit('increment')` is called:
114+
As we did before, we need to trigger the `click` event on the `<button>` element. Then, we use `emitted('increment')` to make sure the right values are emitted.
91115

92116
```js
93-
test('emits and event with count when clicked', () => {
117+
test('emits an event with count when clicked', () => {
94118
const wrapper = mount(Counter)
95119

96-
wrapper.find('button').trigger('click')
97120
wrapper.find('button').trigger('click')
98121
wrapper.find('button').trigger('click')
99122

100-
expect(wrapper.emitted('increment')).toHaveLength(3)
101-
expect(wrapper.emitted('increment')[0]).toEqual([1])
102-
expect(wrapper.emitted('increment')[1]).toEqual([2])
103-
expect(wrapper.emitted('increment')[2]).toEqual([3])
123+
// We have "clicked" twice, so the array of `increment` should
124+
// have two values.
125+
expect(wrapper.emitted('increment')).toHaveLength(2)
126+
127+
// Then, we can make sure each element of `wrapper.emitted('increment')`
128+
// contains an array with the expected object.
129+
expect(wrapper.emitted('increment')[0]).toEqual([
130+
{
131+
count: 1,
132+
isEven: false
133+
}
134+
])
135+
136+
expect(wrapper.emitted('increment')[1]).toEqual([
137+
{
138+
count: 2,
139+
isEven: true
140+
}
141+
])
104142
})
105143
```
106144

145+
Testing complex event payloads such as Objects is no different from testing simple values such as numbers or strings.
146+
107147
## Composition API
108148

109149
If you are using the Composition API, you will be calling `context.emit()` instead of `this.$emit()`. `emitted()` captures events from both, so you can test your component using the same techniques described here.
@@ -112,4 +152,4 @@ If you are using the Composition API, you will be calling `context.emit()` inste
112152

113153
- Use `emitted()` to access the events emitted from a Vue component.
114154
- `emitted(eventName)` returns an array, where each element represents one event emitted.
115-
- Arguments are stored in `emitted(eventName)[index]` in an array, in the same order they are emitted.
155+
- Arguments are stored in `emitted(eventName)[index]` in an array in the same order they are emitted.

0 commit comments

Comments
 (0)