Skip to content

Commit 8ac6d44

Browse files
authored
docs(zh): updated guide docs 950763f...a0b40f0 (vuejs#1573)
* docs(zh): updated guide docs 950763f...a0b40f0 * docs(zh): finished all translation * Update getting-started.md * Update testing-async-components.md * Update testing-async-components.md * Update usage-without-a-build-step-node.md * Update useful-libraries-for-testing.md * Update using-with-vuex.md * Update testing-async-components.md
1 parent 869b096 commit 8ac6d44

11 files changed

+189
-63
lines changed

docs/zh/guides/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
!!!include(docs/zh/guides/testing-single-file-components-with-jest.md)!!!
88
!!!include(docs/zh/guides/testing-single-file-components-with-mocha-webpack.md)!!!
99
!!!include(docs/zh/guides/testing-single-file-components-with-karma.md)!!!
10+
!!!include(docs/zh/guides/usage-without-a-build-step-node.md)!!!
1011
!!!include(docs/zh/guides/testing-async-components.md)!!!
1112
!!!include(docs/zh/guides/using-with-typescript.md)!!!
1213
!!!include(docs/zh/guides/using-with-vue-router.md)!!!

docs/zh/guides/common-tips.md

+17-22
Original file line numberDiff line numberDiff line change
@@ -29,47 +29,42 @@ wrapper.vm // 挂载的 Vue 实例
2929

3030
### 生命周期钩子
3131

32+
<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">在 Vue School 学习如何测试生命周期方法及其区间</a></div>
33+
3234
在使用 `mount``shallowMount` 方法时,你可以期望你的组件响应 Vue 所有生命周期事件。但是请务必注意的是,除非使用 `Wrapper.destory()`,否则 `beforeDestroy``destroyed` _将不会触发_
3335

34-
此外组件在每个测试规范结束时并不会被自动销毁,并且将由用户来决定是否要存根或手动清理那些在测试规范结束前继续运行的任务例如 `setInterval` 或者 `setTimeout`
36+
此外组件在每个测试规范结束时并不会被自动销毁,并且将由用户来决定是否要存根或手动清理那些在测试规范结束前继续运行的任务 (例如 `setInterval` 或者 `setTimeout`)
3537

3638
### 使用 `nextTick` 编写异步测试代码 (新)
3739

38-
默认情况下 Vue 会异步地批量执行更新在下一轮 tick,以避免不必要的 DOM 重绘或者是观察者计算[查看文档](https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列) 了解更多信息
40+
默认情况下 Vue 会异步地批量执行更新 (在下一轮 tick),以避免不必要的 DOM 重绘或者是观察者计算 ([查看文档](https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列) 了解更多信息)
3941

4042
这意味着你在更新会引发 DOM 变化的属性后**必须**等待一下。你可以使用 `Vue.nextTick()`
4143

4244
```js
4345
it('updates text', async () => {
4446
const wrapper = mount(Component)
45-
wrapper.trigger('click')
46-
await Vue.nextTick()
47+
await wrapper.trigger('click')
4748
expect(wrapper.text()).toContain('updated')
49+
await wrapper.trigger('click')
50+
wrapper.text().toContain('some different text')
4851
})
4952

50-
// 或者你不希望使用async/await
53+
// 或者你不希望使用 async/await
5154
it('render text', done => {
5255
const wrapper = mount(TestComponent)
53-
wrapper.trigger('click')
54-
Vue.nextTick(() => {
55-
wrapper.text().toContain('some text')
56-
wrapper.trigger('click')
57-
Vue.nextTick(() => {
56+
wrapper.trigger('click').then(() => {
57+
wrapper.text().toContain('updated')
58+
wrapper.trigger('click').then(() => {
5859
wrapper.text().toContain('some different text')
5960
done()
6061
})
6162
})
6263
})
6364
```
6465

65-
下面的方法通常会导致观察者更新,你需要等待下一轮 tick:
66+
可以在[测试异步行为](../guides/README.md#测试异步行为)了解更多。
6667

67-
- `setChecked`
68-
- `setData`
69-
- `setSelected`
70-
- `setProps`
71-
- `setValue`
72-
- `trigger`
7368

7469
### 断言触发的事件
7570

@@ -139,13 +134,13 @@ expect(wrapper.emitted().foo[1]).toEqual([123])
139134
**测试代码**
140135

141136
```js
142-
import { shallowMount } from '@vue/test-utils'
137+
import { mount } from '@vue/test-utils'
143138
import ParentComponent from '@/components/ParentComponent'
144139
import ChildComponent from '@/components/ChildComponent'
145140

146141
describe('ParentComponent', () => {
147142
it("displays 'Emitted!' when custom event is emitted", () => {
148-
const wrapper = shallowMount(ParentComponent)
143+
const wrapper = mount(ParentComponent)
149144
wrapper.find(ChildComponent).vm.$emit('custom')
150145
expect(wrapper.html()).toContain('Emitted!')
151146
})
@@ -182,7 +177,7 @@ _想查阅所有选项的完整列表,请移步该文档的[挂载选项](../a
182177

183178
### 仿造 Transitions
184179

185-
尽管在大多数情况下使用 `await Vue.nextTick()` 效果很好,但是在某些情况下还需要一些额外的工作。这些问题将在 `vue-test-utils` 移出 beta 版本之前解决。其中一个例子是 Vue 提供的带有 `<transition>` 包装器的单元测试组件。
180+
尽管在大多数情况下使用 `await Vue.nextTick()` 效果很好,但是在某些情况下还需要一些额外的工作。这些问题将在 `vue-test-utils` 移出 beta 版本之前解决。其中一个例子是 Vue 提供的带有 `<transition>` 包装器的单元测试组件。
186181

187182
```vue
188183
<template>
@@ -252,7 +247,7 @@ test('should render Foo, then hide it', async () => {
252247

253248
#### 避免 `setData`
254249

255-
另一种选择是通过编写两个测试来简单地避免使用 `setData`,这要求我们在使用 `mount` 或者 `shallowMount` 时需要指定一些 选项
250+
另一种选择是通过编写两个测试来简单地避免使用 `setData`,这要求我们在使用 `mount` 或者 `shallowMount` 时需要指定一些选项
256251

257252
```js
258253
test('should render Foo', async () => {
@@ -287,7 +282,7 @@ test('should not render Foo', async () => {
287282
如果你在为一个特定的应用撰写组件,你可以在你的测试入口处一次性设置相同的全局插件和混入。但是有些情况下,比如测试一个可能会跨越不同应用共享的普通的组件套件的时候,最好还是在一个更加隔离的设置中测试你的组件,不对全局的 `Vue` 构造函数注入任何东西。我们可以使用 [`createLocalVue`](../api/createLocalVue.md) 方法来存档它们:
288283

289284
```js
290-
import { createLocalVue } from '@vue/test-utils'
285+
import { createLocalVue, mount } from '@vue/test-utils'
291286

292287
// 创建一个扩展的 `Vue` 构造函数
293288
const localVue = createLocalVue()

docs/zh/guides/dom-events.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 测试键盘、鼠标等其它 DOM 事件
22

3+
<div class="vueschool"><a href="https://vueschool.io/lessons/traversing-the-dom?friend=vuejs" target="_blank" rel="sponsored noopener" title="Learn to traverse and interact with the DOM with a free video lesson from Vue School">在 Vue School 免费学习如何遍历 DOM 并与其互动的课程</a></div>
4+
35
### 触发事件
46

57
`Wrapper` 暴露了一个 `trigger` 方法。它可以用来触发 DOM 事件。
@@ -207,7 +209,3 @@ describe('Key event tests', () => {
207209
| home | 36 |
208210
| pageup | 33 |
209211
| pagedown | 34 |
210-
211-
### 重要事项
212-
213-
Vue Test Utils 是同步触发事件。因此 `Vue.nextTick` 不是必须的。

docs/zh/guides/getting-started.md

+32-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## 起步
22

3+
<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">学习如何用 Vue Test Utils、Jest 起步并测试 Vue 组件</a></div>
4+
35
### 安装
46

57
快速尝鲜 Vue Test Utils 的办法就是克隆我们的 demo 仓库再加上基本的设置和依赖安装。
@@ -10,6 +12,22 @@ cd vue-test-utils-getting-started
1012
npm install
1113
```
1214

15+
如果你已经有一个通过 [Vue CLI](https://cli.vuejs.org/zh/) 创建的工程并想支持其测试,则可以运行:
16+
17+
```bash
18+
# unit testing
19+
vue add @vue/unit-jest
20+
21+
# or:
22+
vue add @vue/unit-mocha
23+
24+
# end-to-end
25+
vue add @vue/e2e-cypress
26+
27+
# or:
28+
vue add @vue/e2e-nightwatch
29+
```
30+
1331
你会发现该工程包含了一个简单的组件 `counter.js`
1432

1533
```js
@@ -104,30 +122,31 @@ it('button click should increment the count', () => {
104122

105123
为了测试计数器中的文本是否已经更新,我们需要了解 `nextTick`
106124

107-
### 使用 `nextTick`
125+
### 使用 `nextTick` 与 await
108126

109-
Vue 会异步的将未生效的 DOM 批量更新,避免因数据反复变化而导致不必要的渲染。
127+
任何导致操作 DOM 的改变都应该在断言之前 await `nextTick` 函数。因为 Vue 会对未生效的 DOM 进行批量*异步更新*,避免因数据反复变化而导致不必要的渲染。
110128

111-
_你可以阅读[Vue 文档](https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列)了解更多关于异步指更新的信息。_
129+
*你可以阅读[Vue 文档](https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列)了解更多关于异步指更新的信息。*
112130

113-
更新会引发 DOM 变化的属性后,我们需要使用 `Vue.nextTick()` 等待 Vue 完成 DOM 更新。
131+
在更新响应式 property 之后,我们可以直接 await 类似 `trigger``trigger.vm.$nextTick` 方法,等待 Vue 完成 DOM 更新。在这个计数器的示例中,设置 `count` property 会在运行下一个 tick 之后引发 DOM 变化
114132

115-
在编写测试代码时,我们可以在异步函数里使用`await` `Vue.nextTick()`
133+
我们看看如何在测试中撰写一个 async 函数并 `await trigger()`
116134

117135
```js
118136
it('button click should increment the count text', async () => {
119137
expect(wrapper.text()).toContain('0')
120138
const button = wrapper.find('button')
121-
button.trigger('click')
122-
await Vue.nextTick()
139+
await button.trigger('click')
123140
expect(wrapper.text()).toContain('1')
124141
})
125142
```
126143

144+
`trigger` 返回一个可以像上述示例一样被 await 或像普通 Promise 回调一样被 `then` 链式调用的 Promise。诸如 `trigger` 的方法内部仅仅返回 `Vue.nextTick`。你可以在[测试异步组件](../guides/README.md#测试异步组件)了解更多。
145+
127146
当你在测试代码中使用 `nextTick` 时,请注意任何在其内部被抛出的错误可能都不会被测试运行器捕获,因为其内部使用了 Promise。关于这个问题有两个建议:要么你可以在测试的一开始将 Vue 的全局错误处理器设置为 `done` 回调,要么你可以在调用 `nextTick` 时不带参数让其作为一个 Promise 返回:
128147

129148
```js
130-
// 这不会被捕获
149+
// 错误不会被捕获
131150
it('will time out', done => {
132151
Vue.nextTick(() => {
133152
expect(true).toBe(false)
@@ -156,7 +175,9 @@ it('will catch the error using async/await', async () => {
156175
})
157176
```
158177

159-
### 下一步是什么
178+
### 接下来
179+
160180

161-
- [选择一个测试运行器](./choosing-a-test-runner.md)以把 Vue Test Utils 集成到你的工程里。
162-
- 移步[撰写测试的常见技巧](./common-tips.md)以学习更多。
181+
- 移步[编写测试的常见技巧](./README.md#明白要测试的是什么)以学习更多。
182+
- [选择一个测试运行器](./README.md#选择一个测试运行器)以把 Vue Test Utils 集成到你的工程里。
183+
- 学习更多[异步测试行为](./README.md#异步测试行为)

docs/zh/guides/testing-async-components.md

+36-15
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@ Vue 会异步的将未生效的 DOM 批量更新,避免因数据反复变化
1111

1212
_你可以阅读[Vue 文档](https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列)了解更多关于异步指更新的信息。_
1313

14-
在实践中,往往意味着你在更新会引发 DOM 变化的属性后必须使用 `Vue.nextTick()` 来等待 Vue 完成 DOM 更新。
15-
16-
使用 `Vue.nextTick()` 最简单的方法是在你的测试代码中使用异步函数:
14+
在实践中,这意味着变更一个响应式 property 之后,为了断言这个变化,你的测试需要等待 Vue 完成更新。其中一种办法是使用 `await Vue.nextTick()`,一个更简单且清晰的方式则是 `await` 那个你变更状态的方法,例如 `trigger`
1715

1816
```js
19-
// 在文件头部引用Vue库
20-
import Vue from 'vue'
17+
// 在测试框架中,编写一个测试用例
18+
it('button click should increment the count text', async () => {
19+
expect(wrapper.text()).toContain('0')
20+
const button = wrapper.find('button')
21+
await button.trigger('click')
22+
expect(wrapper.text()).toContain('1')
23+
})
24+
```
2125

22-
// 其它的代码片断...
26+
和等待上述触发等价:
2327

24-
// 在测试框架中,编写一个测试用例
28+
```js
2529
it('button click should increment the count text', async () => {
2630
expect(wrapper.text()).toContain('0')
2731
const button = wrapper.find('button')
@@ -31,11 +35,20 @@ it('button click should increment the count text', async () => {
3135
})
3236
```
3337

38+
可以被 await 的方法有:
39+
40+
- [setData](../api/wrapper/README.md#setdata)
41+
- [setValue](../api/wrapper/README.md#setvalue)
42+
- [setChecked](../api/wrapper/README.md#setchecked)
43+
- [setSelected](../api/wrapper/README.md#setselected)
44+
- [setProps](../api/wrapper/README.md#setprops)
45+
- [trigger](../api/wrapper/README.md#trigger)
46+
3447
## 来自外部行为的更新
3548

3649
在 Vue 之外最常见的一种异步行为就是在 Vuex 中进行 API 调用。以下示例将展示如何测试在 Vuex 中进行 API 调用的方法。本示例使用 Jest 运行测试并模拟 HTTP 库`axios`。可以在[这里](https://jestjs.io/docs/en/manual-mocks.html#content)找到有关 Jest Mock 的更多信息。
3750

38-
`axios` Mock 的实现如下所示:
51+
`axios` mock 的实现如下所示:
3952

4053
```js
4154
export default {
@@ -47,7 +60,7 @@ export default {
4760

4861
```html
4962
<template>
50-
<button @click="fetchResults" />
63+
<button @click="fetchResults">{{ value }}</button>
5164
</template>
5265

5366
<script>
@@ -75,12 +88,14 @@ export default {
7588
```js
7689
import { shallowMount } from '@vue/test-utils'
7790
import Foo from './Foo'
78-
jest.mock('axios')
91+
jest.mock('axios', () => ({
92+
get: Promise.resolve('value')
93+
}))
7994

8095
it('fetches async when a button is clicked', () => {
8196
const wrapper = shallowMount(Foo)
8297
wrapper.find('button').trigger('click')
83-
expect(wrapper.vm.value).toBe('value')
98+
expect(wrapper.text()).toBe('value')
8499
})
85100
```
86101

@@ -91,15 +106,15 @@ it('fetches async when a button is clicked', done => {
91106
const wrapper = shallowMount(Foo)
92107
wrapper.find('button').trigger('click')
93108
wrapper.vm.$nextTick(() => {
94-
expect(wrapper.vm.value).toBe('value')
109+
expect(wrapper.text()).toBe('value')
95110
done()
96111
})
97112
})
98113
```
99114

100115
setTimeout 也可以使测试通过的原因是,Promise 回调的微任务队列会排在 setTimeout 回调的微任务队列之前。这意味着当 setTimeout 回调执行时,微任务队列上的所有 Promise 回调已经被执行过了。另一方面,`$nextTick` 也存在调度微任务的情况,但是由于微任务队列是先进先出的,因此也保证了在进行断言时已经处理完所有的 Promise 回调。请参阅[此处]https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/)了解更多详细说明。
101116

102-
另外一个使用 `async` 方法的解决方案是使用 npm 仓库中的 `flush-promises``flush-promises` 会刷新所有处于 pending 状态或 resolved 状态的 Promise。你可以用 `await` 语句来等待 `flushPromises` 刷新 Promise 的状态,这样可以提升你代码的可读性。
117+
另外一个使用 `async` 方法的解决方案是使用类似 [flush-promises](https://www.npmjs.com/package/flush-promises) 的包`flush-promises` 会刷新所有处于 pending 状态或 resolved 状态的 Promise。你可以用 `await` 语句来等待 `flushPromises` 刷新 Promise 的状态,这样可以提升你代码的可读性。
103118

104119
修改以后的测试代码:
105120

@@ -113,8 +128,14 @@ it('fetches async when a button is clicked', async () => {
113128
const wrapper = shallowMount(Foo)
114129
wrapper.find('button').trigger('click')
115130
await flushPromises()
116-
expect(wrapper.vm.value).toBe('value')
131+
expect(wrapper.text()).toBe('value')
117132
})
118133
```
119134

120-
相同的技术细节也可以应用在处理 Vue Actions 上,默认情况下,它也会返回一个 Promise。
135+
相同的技术细节也可以应用在处理 Vuex 的 action 上,默认情况下,它也会返回一个 Promise。
136+
137+
#### 为什么不使用 `await button.trigger()`
138+
139+
如之前所解释的,Vue 更新其组件和完成其 Promise 对象的时机不同,如 `axios` 解析出的那个。
140+
141+
一个易于遵循的规则是在诸如 `trigger``setProps` 的变更时始终使用 `await`。如果你的代码依赖一些诸如 `axios` 的异步操作,也要为 `flushPromises` 加入一个 await。

docs/zh/guides/testing-single-file-components-with-jest.md

+10
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@
44
55
Jest 是一个由 Facebook 开发的测试运行器,致力于提供一个“bettery-included”单元测试解决方案。你可以在其[官方文档](https://jestjs.io/)学习到更多 Jest 的知识。
66

7+
<div class="vueschool"><a href="https://vueschool.io/courses/learn-how-to-test-vuejs-components?friend=vuejs" target="_blank" rel="sponsored noopener" title="Learn how to use Jest and Vue Test Utils to test Single File Components with Vue School">在 Vue School 学习如何使用 Jest 测试单文件组件</a></div>
8+
79
### 安装 Jest
810

911
我们假定你在一开始已经安装并配置好了 webpack、vue-loader 和 Babel——例如通过 `vue-cli` 创建了 `webpack-simple` 模板脚手架。
1012

13+
> 另一种方案,如果你在使用 Vue CLI 构建你的工程也可以使用 [cli-plugin-unit-jest](https://cli.vuejs.org/core-plugins/unit-jest.html#injected-commands) 插件来运行 Jest 测试。
14+
>
15+
> 跳到[在 Jest 中处理单文件组件](#在 Jest 中处理单文件组件)并遵循其指示以处理你的 Vue 单文件组件。
16+
>
17+
> 如果你在使用 Babel 进行转译 (这是创建新工程的默认配置),你也需要在项目中的 `package.json` 配置 Jest 的 JavaScript 转换,参考[为 Jest 配置 Babel](#为-jest-配置-babel),不过这样你应该跳过该章节其余的部分。
18+
1119
我们要做的第一件事就是安装 Jest 和 Vue Test Utils:
1220

1321
```bash
@@ -55,6 +63,8 @@ npm install --save-dev vue-jest
5563

5664
> **注意:**`vue-jest` 目前并不支持 `vue-loader` 所有的功能,比如自定义块和样式加载。额外的,诸如代码分隔等 webpack 特有的功能也是不支持的。如果要使用这些不支持的特性,你需要用 Mocha 取代 Jest 来运行你的测试,同时用 webpack 来编译你的组件。想知道如何起步,请阅读教程里的[用 Mocha + webpack 测试单文件组件](./testing-single-file-components-with-mocha-webpack.md)
5765
66+
> **注意:**如果你使用了 Babel 7 或更高版本,你需要在你的 `devDependencies` 里添加 [babel-bridge](https://github.com/babel/babel-bridge) (`$ npm install --save-dev babel-core@^7.0.0-bridge.0`)。
67+
5868
### 处理 webpack 别名
5969

6070
如果你在 webpack 中配置了别名解析,比如把 `@` 设置为 `/src` 的别名,那么你也需要用 `moduleNameMapper` 选项为 Jest 增加一个匹配配置:

docs/zh/guides/testing-single-file-components-with-karma.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ Woohoo,我们的测试跑起来了!
136136
npm install --save-dev karma-coverage cross-env
137137
```
138138

139-
我们会使用 `cross-env` 来设置一个 `BABEL_ENV` 环境变量。这样我们就可以在编译测试的时候使用 `babel-plugin-istanbul`——因为我们不想在生产环境下引入 `babel-plugin-istanbul`
139+
我们会使用 `cross-env` 来设置一个 `NODE_ENV` 环境变量。这样我们就可以在编译测试的时候使用 `babel-plugin-istanbul`——因为我们不想在生产环境下引入 `babel-plugin-istanbul`
140140

141141
```
142142
npm install --save-dev babel-plugin-istanbul
143143
```
144144

145-
更新你的 `.babelrc` 文件,在因测试设置了 `BABEL_ENV` 时使用 `babel-plugin-istanbul`
145+
更新你的 `.babelrc` 文件,在因测试设置了 `NODE_ENV` 时使用 `babel-plugin-istanbul`
146146

147147
```json
148148
{
@@ -174,13 +174,13 @@ module.exports = function(config) {
174174
}
175175
```
176176

177-
然后更新 `test` 脚本来设置 `BABEL_ENV`
177+
然后更新 `test` 脚本来设置 `NODE_ENV`
178178

179179
```json
180180
// package.json
181181
{
182182
"scripts": {
183-
"test": "cross-env BABEL_ENV=test karma start --single-run"
183+
"test": "cross-env NODE_ENV=test karma start --single-run"
184184
}
185185
}
186186
```

0 commit comments

Comments
 (0)