From 378242dbffa2d89c20b7215e3560ef7c17506cc3 Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Sat, 3 Feb 2018 00:18:37 +0800 Subject: [PATCH 1/2] [docs][zh-cn] synced updates from #3508a16 to #755cd09 --- docs/zh-cn/README.md | 10 +- docs/zh-cn/SUMMARY.md | 8 +- docs/zh-cn/api/README.md | 9 +- docs/zh-cn/api/components/RouterLinkStub.md | 20 ++ docs/zh-cn/api/wrapper-array/filter.md | 23 ++ docs/zh-cn/api/wrapper-array/hasStyle.md | 25 --- docs/zh-cn/api/wrapper-array/setComputed.md | 25 --- docs/zh-cn/api/wrapper-array/visible.md | 22 ++ docs/zh-cn/api/wrapper/hasStyle.md | 24 --- docs/zh-cn/api/wrapper/visible.md | 21 ++ docs/zh-cn/guides/README.md | 1 + docs/zh-cn/guides/common-tips.md | 6 +- docs/zh-cn/guides/testing-SFCs-with-jest.md | 2 +- docs/zh-cn/guides/testing-SFCs-with-karma.md | 202 ++++++++++++++++++ .../guides/testing-SFCs-with-mocha-webpack.md | 2 +- docs/zh-cn/guides/using-with-vuex.md | 131 +++++++++++- 16 files changed, 440 insertions(+), 91 deletions(-) create mode 100644 docs/zh-cn/api/components/RouterLinkStub.md create mode 100644 docs/zh-cn/api/wrapper-array/filter.md delete mode 100644 docs/zh-cn/api/wrapper-array/hasStyle.md delete mode 100644 docs/zh-cn/api/wrapper-array/setComputed.md create mode 100644 docs/zh-cn/api/wrapper-array/visible.md delete mode 100644 docs/zh-cn/api/wrapper/hasStyle.md create mode 100644 docs/zh-cn/api/wrapper/visible.md create mode 100644 docs/zh-cn/guides/testing-SFCs-with-karma.md diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md index f0464bdd2..fe70511e4 100644 --- a/docs/zh-cn/README.md +++ b/docs/zh-cn/README.md @@ -2,6 +2,8 @@ `vue-test-utils` 是 Vue.js 官方的单元测试实用工具库。 +## 目录 + * [教程](guides/README.md) * [起步](guides/getting-started.md) * [常用技巧](guides/common-tips.md) @@ -9,6 +11,7 @@ * [选择一个测试运行器](guides/choosing-a-test-runner.md) * [用 Jest 测试单文件组件](guides/testing-SFCs-with-jest.md) * [用 Mocha 和 webpack 测试单文件组件](guides/testing-SFCs-with-mocha-webpack.md) + * [用 Karma 测试单文件组件](guides/testing-SFCs-with-karma.md) * [测试异步行为](guides/testing-async-components.md) * [配合 Vue Router 使用](guides/using-with-vue-router.md) * [配合 Vuex 实用](guides/using-with-vuex.md) @@ -36,35 +39,34 @@ * [destroy](api/wrapper/destroy.md) * [find](api/wrapper/find.md) * [findAll](api/wrapper/findAll.md) - * [hasStyle](api/wrapper/hasStyle.md) * [html](api/wrapper/html.md) * [is](api/wrapper/is.md) * [isEmpty](api/wrapper/isEmpty.md) * [isVueInstance](api/wrapper/isVueInstance.md) * [name](api/wrapper/name.md) * [props](api/wrapper/props.md) - * [setComputed](api/wrapper/setComputed.md) * [setData](api/wrapper/setData.md) * [setMethods](api/wrapper/setMethods.md) * [setProps](api/wrapper/setProps.md) * [text](api/wrapper/text.md) * [trigger](api/wrapper/trigger.md) * [update](api/wrapper/update.md) + * [visible](api/wrapper/visible.md) * [WrapperArray](api/wrapper-array/README.md) * [at](api/wrapper-array/at.md) * [contains](api/wrapper-array/contains.md) * [exists](api/wrapper/exists.md) * [destroy](api/wrapper-array/destroy.md) - * [hasStyle](api/wrapper-array/hasStyle.md) + * [filter](api/wrapper-array/filter.md) * [is](api/wrapper-array/is.md) * [isEmpty](api/wrapper-array/isEmpty.md) * [isVueInstance](api/wrapper-array/isVueInstance.md) - * [setComputed](api/wrapper-array/setComputed.md) * [setData](api/wrapper-array/setData.md) * [setMethods](api/wrapper-array/setMethods.md) * [setProps](api/wrapper-array/setProps.md) * [trigger](api/wrapper-array/trigger.md) * [update](api/wrapper-array/update.md) + * [visible](api/wrapper-array/visible.md) * [组件](api/components/README.md) * [TransitionStub](api/components/TransitionStub.md) * [TransitionGroupStub](api/components/TransitionGroupStub.md) diff --git a/docs/zh-cn/SUMMARY.md b/docs/zh-cn/SUMMARY.md index ec3661f36..9381d2edc 100644 --- a/docs/zh-cn/SUMMARY.md +++ b/docs/zh-cn/SUMMARY.md @@ -7,6 +7,7 @@ * [选择一个测试运行器](guides/choosing-a-test-runner.md) * [用 Jest 测试单文件组件](guides/testing-SFCs-with-jest.md) * [用 Mocha 和 webpack 测试单文件组件](guides/testing-SFCs-with-mocha-webpack.md) + * [用 Karma 测试单文件组件](guides/testing-SFCs-with-karma.md) * [测试异步行为](guides/testing-async-components.md) * [配合 Vue Router 使用](guides/using-with-vue-router.md)  * [配合 Vuex 使用](guides/using-with-vuex.md) @@ -34,7 +35,6 @@ * [destroy](api/wrapper/destroy.md) * [find](api/wrapper/find.md) * [findAll](api/wrapper/findAll.md) - * [hasStyle](api/wrapper/hasStyle.md) * [html](api/wrapper/html.md) * [is](api/wrapper/is.md) * [isEmpty](api/wrapper/isEmpty.md) @@ -47,24 +47,26 @@ * [text](api/wrapper/text.md) * [trigger](api/wrapper/trigger.md) * [update](api/wrapper/update.md) + * [visible](api/wrapper/visible.md) * [WrapperArray](api/wrapper-array/README.md) * [at](api/wrapper-array/at.md) * [contains](api/wrapper-array/contains.md) * [exists](api/wrapper/exists.md) * [destroy](api/wrapper-array/destroy.md) - * [hasStyle](api/wrapper-array/hasStyle.md) + * [filter](api/wrapper-array/filter.md) * [is](api/wrapper-array/is.md) * [isEmpty](api/wrapper-array/isEmpty.md) * [isVueInstance](api/wrapper-array/isVueInstance.md) - * [setComputed](api/wrapper-array/setComputed.md) * [setData](api/wrapper-array/setData.md) * [setMethods](api/wrapper-array/setMethods.md) * [setProps](api/wrapper-array/setProps.md) * [trigger](api/wrapper-array/trigger.md) * [update](api/wrapper-array/update.md) + * [visible](api/wrapper-array/visible.md) * [组件](api/components/README.md) * [TransitionStub](api/components/TransitionStub.md) * [TransitionGroupStub](api/components/TransitionGroupStub.md) + * [RouterLinkStub](api/components/RouterLinkStub.md) * [选择器](api/selectors.md) * [createLocalVue](api/createLocalVue.md) * [配置](api/config.md) diff --git a/docs/zh-cn/api/README.md b/docs/zh-cn/api/README.md index 9bd47ef48..5689a16c9 100644 --- a/docs/zh-cn/api/README.md +++ b/docs/zh-cn/api/README.md @@ -14,6 +14,8 @@ - [provide](./options.md#provide) - [其它选项](./options.md#other-options) * [Wrapper](./wrapper/README.md) + * [attributes](./wrapper/attributes.md) + * [classes](./wrapper/classes.md) * [contains](./wrapper/contains.md) * [emitted](./wrapper/emitted.md) * [emittedByOrder](./wrapper/emittedByOrder.md) @@ -24,35 +26,34 @@ * [hasAttribute](./wrapper/hasAttribute.md) * [hasClass](./wrapper/hasClass.md) * [hasProp](./wrapper/hasProp.md) - * [hasStyle](./wrapper/hasStyle.md) * [html](./wrapper/html.md) * [is](./wrapper/is.md) * [isEmpty](./wrapper/isEmpty.md) * [isVueInstance](./wrapper/isVueInstance.md) * [name](./wrapper/name.md) * [props](./wrapper/props.md) - * [setComputed](./wrapper/setComputed.md) * [setData](./wrapper/setData.md) * [setMethods](./wrapper/setMethods.md) * [setProps](./wrapper/setProps.md) * [text](./wrapper/text.md) * [trigger](./wrapper/trigger.md) * [update](./wrapper/update.md) + * [visible](./wrapper/visible.md) * [WrapperArray](./wrapper-array/README.md) * [at](./wrapper-array/at.md) * [contains](./wrapper-array/contains.md) * [exists](./wrapper/exists.md) * [destroy](./wrapper-array/destroy.md) - * [hasStyle](./wrapper-array/hasStyle.md) + * [filter](./wrapper-array/filter.md) * [is](./wrapper-array/is.md) * [isEmpty](./wrapper-array/isEmpty.md) * [isVueInstance](./wrapper-array/isVueInstance.md) - * [setComputed](./wrapper-array/setComputed.md) * [setData](./wrapper-array/setData.md) * [setMethods](./wrapper-array/setMethods.md) * [setProps](./wrapper-array/setProps.md) * [trigger](./wrapper-array/trigger.md) * [update](./wrapper-array/update.md) + * [visible](./wrapper-array/visible.md) * [组件](./components/README.md) * [TransitionStub](./components/TransitionStub.md) * [TransitionGroupStub](./components/TransitionGroupStub.md) diff --git a/docs/zh-cn/api/components/RouterLinkStub.md b/docs/zh-cn/api/components/RouterLinkStub.md new file mode 100644 index 000000000..b305a76a4 --- /dev/null +++ b/docs/zh-cn/api/components/RouterLinkStub.md @@ -0,0 +1,20 @@ +# `RouterLinkStub` + +一个用来存根 Vue Router 中 `router-link` 组件的组件。 + +你可以在渲染树中使用这个组件查找一个 `router-link` 组件。 + +- **用法:** + +在挂载选项中将其设置为一个存根: + +```js +import { mount, RouterLinkStub } from '@vue/test-utils' + +const wrapper = mount(Component, { + stubs: { + RouterLink: RouterLinkStub + } +}) +expect(wrapper.find(RouterLinkStub).props().to).toBe('/some/path') +``` diff --git a/docs/zh-cn/api/wrapper-array/filter.md b/docs/zh-cn/api/wrapper-array/filter.md new file mode 100644 index 000000000..9237c2828 --- /dev/null +++ b/docs/zh-cn/api/wrapper-array/filter.md @@ -0,0 +1,23 @@ +# `filter(predicate)` + +用一个针对 `Wrapper` 的断言函数过滤 `WrapperArray`。 + +该方法的行为和 [Array.prototype.filter](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) 相同。 + +- **参数:** + - `{function} predicate` + +- **返回值:** `{WrapperArray}` + +一个新的 `WrapperArray` 实例,该实例包含了经过断言函数处理后返回真值的 `Wrapper` 实例。 + +- **示例:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = shallow(Foo) +const filteredDivArray = wrapper.findAll('div').filter(w => !w.hasClass('filtered')) +``` diff --git a/docs/zh-cn/api/wrapper-array/hasStyle.md b/docs/zh-cn/api/wrapper-array/hasStyle.md deleted file mode 100644 index 69af37a01..000000000 --- a/docs/zh-cn/api/wrapper-array/hasStyle.md +++ /dev/null @@ -1,25 +0,0 @@ -# `hasStyle(style, value)` - -断言 `WrapperArray` 中的每一个 `Wrapper` 的 DOM 节点都有样式的匹配值。 - -如果 `Wrapper` 的 DOM 节点有 `style` 样式值匹配 `value` 则返回 `true`。 - -**注意:当运行在 `jsdom` 中的时候只会匹配内联样式。** - -- **参数:** - - `{string} style` - - `{string} value` - -- **返回值:**`{boolean}` - -- **示例:** - -```js -import { mount } from '@vue/test-utils' -import { expect } from 'chai' -import Foo from './Foo.vue' - -const wrapper = mount(Foo) -const divArray = wrapper.findAll('div') -expect(divArray.hasStyle('color', 'red')).toBe(true) -``` diff --git a/docs/zh-cn/api/wrapper-array/setComputed.md b/docs/zh-cn/api/wrapper-array/setComputed.md deleted file mode 100644 index 2ac0304f3..000000000 --- a/docs/zh-cn/api/wrapper-array/setComputed.md +++ /dev/null @@ -1,25 +0,0 @@ -# `setComputed(computedObjects)` - -为 `WrapperArray` 的每个 `Wrapper` `vm` 都设置计算属性并强行更新。 - -**注意:该包裹器必须包含一个 Vue 示例。** -**注意:每个 Vue 示例必须已经有被传入 `setComputed` 的计算属性。** - -- **参数:** - - `{Object} computed properties` - -- **示例:** - -```js -import { mount } from '@vue/test-utils' -import Foo from './Foo.vue' -import Bar from './Bar.vue' - -const wrapper = mount(Foo) -const barArray = wrapper.findAll(Bar) - -barArray.setComputed({ - computed1: 'new-computed1', - computed2: 'new-computed2' -}) -``` diff --git a/docs/zh-cn/api/wrapper-array/visible.md b/docs/zh-cn/api/wrapper-array/visible.md new file mode 100644 index 000000000..360d5fb25 --- /dev/null +++ b/docs/zh-cn/api/wrapper-array/visible.md @@ -0,0 +1,22 @@ +# `visible()` + +断言每个 `WrapperArray` 中的每个 `Wrapper` 是否可见。 + +如果至少一个元素的祖先拥有 `display: none` 或 `visibility: hidden` 样式则返回 `false`。 + +这可以用于断言一个组件是否被 `v-show` 所隐藏。 + +- **返回值:** `{boolean}` + +- **示例:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.visible()).toBe(true) +expect(wrapper.findAll('.is-not-visible').visible()).toBe(false) +expect(wrapper.findAll('.is-visible').visible()).toBe(true) +``` diff --git a/docs/zh-cn/api/wrapper/hasStyle.md b/docs/zh-cn/api/wrapper/hasStyle.md deleted file mode 100644 index 543daf3e7..000000000 --- a/docs/zh-cn/api/wrapper/hasStyle.md +++ /dev/null @@ -1,24 +0,0 @@ -# `hasStyle(style, value)` - -断言 `Wrapper` DOM 节点有匹配的样式值。 - -如果 `Wrapper` DOM 节点有 `style` 属性值为 `value` 则返回 `true`。 - -**注意:当运行在 `jsdom` 中时只会检测内联样式。** - -- **参数:** - - `{string} style` - - `{string} value` - -- **返回值:**`{boolean}` - -- **示例:** - -```js -import { mount } from '@vue/test-utils' -import { expect } from 'chai' -import Foo from './Foo.vue' - -const wrapper = mount(Foo) -expect(wrapper.hasStyle('color', 'red')).toBe(true) -``` diff --git a/docs/zh-cn/api/wrapper/visible.md b/docs/zh-cn/api/wrapper/visible.md new file mode 100644 index 000000000..3caffdc21 --- /dev/null +++ b/docs/zh-cn/api/wrapper/visible.md @@ -0,0 +1,21 @@ +# `visible()` + +断言 `Wrapper` 是否可见。 + +如果有一个祖先元素拥有 `display: none` 或 `visibility: hidden` 样式则返回 `false`。 + +这可以用于断言一个组件是否被 `v-show` 所隐藏。 + +- **返回值:** `{boolean}` + +- **示例:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.visible()).toBe(true) +expect(wrapper.find('.is-not-visible').visible()).toBe(false) +``` diff --git a/docs/zh-cn/guides/README.md b/docs/zh-cn/guides/README.md index 3ab428c5b..27f2478fa 100644 --- a/docs/zh-cn/guides/README.md +++ b/docs/zh-cn/guides/README.md @@ -6,6 +6,7 @@ * [选择一个测试运行器](./choosing-a-test-runner.md) * [用 Jest 测试单文件组件](./testing-SFCs-with-jest.md) * [用 Mocha 和 webpack 测试单文件组件](./testing-SFCs-with-mocha-webpack.md) +* [用 Karma 测试单文件组件](./testing-SFCs-with-karma.md) * [测试异步行为](./testing-async-components.md) * [配合 Vue Router 使用](./using-with-vue-router.md) * [配合 Vuex 实用](./using-with-vuex.md) diff --git a/docs/zh-cn/guides/common-tips.md b/docs/zh-cn/guides/common-tips.md index 69e3ccefd..5b02ac497 100644 --- a/docs/zh-cn/guides/common-tips.md +++ b/docs/zh-cn/guides/common-tips.md @@ -109,7 +109,7 @@ mount(Component, { }) ``` -**注意有些插件会为全局的 Vue 构造函数添加只读属性,比如 Vue Router。这使得我们无法在一个 `localVue` 构造函数上二次安装该插件,或伪造这些属性。** +**注意有些插件会为全局的 Vue 构造函数添加只读属性,比如 Vue Router。这使得我们无法在一个 `localVue` 构造函数上二次安装该插件,或伪造这些只读属性。** ## 仿造注入 @@ -135,3 +135,7 @@ mount(Component, { ## 处理路由 因为路由需要在应用的全局结构中进行定义,且引入了很多组件,所以最好集成到 end-to-end 测试。对于依赖 `vue-router` 功能的独立的组件来说,你可以使用上面提到的技术仿造它们。 + +## 探测样式 + +当你的测试运行在 `jsdom` 中时,可以只探测到内联样式。 diff --git a/docs/zh-cn/guides/testing-SFCs-with-jest.md b/docs/zh-cn/guides/testing-SFCs-with-jest.md index 2d95464ff..38600d48a 100644 --- a/docs/zh-cn/guides/testing-SFCs-with-jest.md +++ b/docs/zh-cn/guides/testing-SFCs-with-jest.md @@ -11,7 +11,7 @@ Jest 是一个由 Facebook 开发的测试运行器,致力于提供一个“be 我们要做的第一件事就是安装 Jest 和 `vue-test-utils`: ```bash -$ npm install --save-dev jest vue-test-utils +$ npm install --save-dev jest @vue/test-utils ``` 然后我们需要在 `package.json` 中定义一个单元测试的脚本。 diff --git a/docs/zh-cn/guides/testing-SFCs-with-karma.md b/docs/zh-cn/guides/testing-SFCs-with-karma.md new file mode 100644 index 000000000..d8d8b2b15 --- /dev/null +++ b/docs/zh-cn/guides/testing-SFCs-with-karma.md @@ -0,0 +1,202 @@ +# Testing Single File Components with Karma + +> An example project for this setup is available on [GitHub](https://github.com/eddyerburgh/vue-test-utils-karma-example). + +Karma is a test runner that launches browsers, runs tests, and reports them back to us. We're going to use the Mocha framework to write the tests. We'll use the chai library for test assertions. + +## Setting up Mocha + +We will assume you are starting with a setup that already has webpack, vue-loader and Babel properly configured - e.g. the `webpack-simple` template scaffolded by `vue-cli`. + +The first thing to do is install the test dependencies: + +``` bash +npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha karma-sourcemap-loader karma-spec-reporter karma-webpack mocha +``` + +Next we need to define a test script in our `package.json`. + +```json +// package.json +{ + "scripts": { + "test": "karma start --single-run" + } +} +``` + +- The `--single-run` flag tells Karma to run the test suite once. + +### Karma Configuration + +Create a karma.conf.js file in the index of the project: + +```js +// karma.conf.js + +var webpackConfig = require('./webpack.config.js') + +module.exports = function (config) { + config.set({ + frameworks: ['mocha'], + + files: [ + 'test/**/*.spec.js' + ], + + preprocessors: { + '**/*.spec.js': ['webpack', 'sourcemap'] + }, + + webpack: webpackConfig, + + reporters: ['spec'], + + browsers: ['Chrome'] + }) +} +``` + +This file is used to configure Karma. + +We need to preprocess our files with webpack. to do that, we add webpack as a preprocessor, and include our webpack config. We can use the webpack config file in the base of the project without changing anything. + +In our configuration, we run the tests in Chrome. To add extra browsers, see [the Browsers section in the Karma docs](http://karma-runner.github.io/2.0/config/browsers.html). + +### Picking an Assertion Library + +[Chai](http://chaijs.com/) is a popular assertion library that is commonly used alongside Mocha. You may also want to check out [Sinon](http://sinonjs.org/) for creating spies and stubs. + +We can install the `karma-chai` plugin to use `chai` in our tests. + +``` bash +npm install --save-dev karma-chai +``` + +### Adding a test + +Create a file in `src` named `Counter.vue`: + +``` html + + + +``` + +And create a test file named `test/Counter.spec.js` with the following code: + +```js +import { expect } from 'chai' +import { shallow } from '@vue/test-utils' +import Counter from '../src/Counter.vue' + +describe('Counter.vue', () => { + it('increments count when button is clicked', () => { + const wrapper = shallow(Counter) + wrapper.find('button').trigger('click') + expect(wrapper.find('div').text()).contains('1') + }) +}) +``` + +And now we can run the tests: + +``` +npm run test +``` + +Woohoo, we got our tests running! + +### Coverage + +To setup code coverage to Karma, we can use the `karma-coverage` plugin. + +By default, `karma-coverage` won't use source maps to map the coverage reports. So we need to use `babel-plugin-istanbul` to make sure the coverage is mapped correctly. + +Install `karma-coverage`, `babel-plugin-istanbul`, and `cross-env`: + +``` +npm install --save-dev karma-coverage cross-env +``` + +We're going to use `cross-env` to set a `BABEL_ENV` environment variable. This way we can use babel-plugin-istanbul when we're compiling for our tests—we don't want to include `babel-plugin-istnabul` when we compile our production code: + +``` +npm install --save-dev babel-plugin-istanbul +``` + +Update your `.babelrc` file to use `babel-plugin-istanbul` when `BABEL_ENV` is set to test: + +```json +{ + "presets": [ + ["env", { "modules": false }], + "stage-3" + ], + "env": { + "test": { + "plugins": ["istanbul"] + } + } +} +``` + +Now update the karma.conf.js file to use coverage. Add `coverage` to the reporters array, and add a coverageReporter field: + +```js +// karma.conf.js + +module.exports = function (config) { + config.set({ + // ... + + reporters: ['spec', 'coverage'], + + coverageReporter: { + dir: './coverage', + reporters: [ + { type: 'lcov', subdir: '.' }, + { type: 'text-summary' } + ] + } + }) +} +``` + +And update the `test` script to set the `BABEL_ENV`: + +```json +// package.json +{ + "scripts": { + "test": "cross-env BABEL_ENV=test karma start --single-run" + } +} +``` + +### Resources + +- [Example project for this setup](https://github.com/eddyerburgh/vue-test-utils-karma-example) +- [Karma](http://karma-runner.github.io/) +- [Mocha](https://mochajs.org/) +- [Chai](http://chaijs.com/) +- [Sinon](http://sinonjs.org/) diff --git a/docs/zh-cn/guides/testing-SFCs-with-mocha-webpack.md b/docs/zh-cn/guides/testing-SFCs-with-mocha-webpack.md index 67fbe5be3..e12062125 100644 --- a/docs/zh-cn/guides/testing-SFCs-with-mocha-webpack.md +++ b/docs/zh-cn/guides/testing-SFCs-with-mocha-webpack.md @@ -165,7 +165,7 @@ describe('Counter.vue', () => { 现在我们运行测试: ``` -npm run unit +npm run test ``` 喔,我们的测试运行起来了! diff --git a/docs/zh-cn/guides/using-with-vuex.md b/docs/zh-cn/guides/using-with-vuex.md index 05daa1973..e37e24950 100644 --- a/docs/zh-cn/guides/using-with-vuex.md +++ b/docs/zh-cn/guides/using-with-vuex.md @@ -1,8 +1,10 @@ # 配合 Vuex 使用 -在本教程中,我们将会看到如何用 `vue-test-utils` 测试组件中的 Vuex。 +在本教程中,我们将会看到如何用 `vue-test-utils` 测试组件中的 Vuex,以及如何测试一个 Vuex store。 -## 伪造 Action +## 在组件中测试 Vuex + +### 伪造 Action 我们来看一些代码。 @@ -259,9 +261,132 @@ describe('Modules.vue', () => { }) ``` +## Testing a Vuex Store + +There are two approaches to testing a Vuex store. The first approach is to unit test the getters, mutations, and actions separately. The second approach is to create a store and test against that. We'll look at both approaches. + +To see how to test a Vuex store, we're going to create a simple counter store. The store will have an `increment` mutation and a `counter` getter. + +```js +// mutations.js +export default { + increment (state) { + state.count++ + } +} + +``` + +```js +// getters.js +export default { + evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd' +} +``` + +### Testing getters, mutations, and actions separately + +Getters, mutations, and actions are all JavaScript functions, so we can test them without using `vue-test-utils` or Vuex. + +The benefit to testing getters, mutations, and actions separately is that your unit tests are detailed. When they fail, you know exactly what is wrong with your code. The downside is that you will need to mock Vuex funtions, like `commit` and `dispatch`. This can lead to a situation where your unit tests pass, but your production code fails because your mocks are incorrect. + +We'll create two test files, mutations.spec.js and getters.spec.js: + +First, let's test the `increment` mutations: + +```js +// mutations.spec.js + +import mutations from './mutations' + +test('increment increments state.count by 1', () => { + const state = { + count: 0 + } + mutations.increment(state) + expect(state.count).toBe(1) +}) +``` + +Now let's test the `evenOrOdd` getter. We can test it by creating a mock `state`, calling the getter with the `state` and checking it returns the correct value. + +```js +// getters.spec.js + +import getters from './getters' + +test('evenOrOdd returns even if state.count is even', () => { + const state = { + count: 2 + } + expect(getters.evenOrOdd(state)).toBe('even') +}) + +test('evenOrOdd returns odd if state.count is even', () => { + const state = { + count: 1 + } + expect(getters.evenOrOdd(state)).toBe('odd') +}) + +``` + +### Testing a running store + +Anopther approach to testing a Vuex store is to create a running store using the store config. + +The benefit of testing creating a running store instance is we don't have to mock any Vuex functions. + +The downside is that when a test breaks, it can be difficult to find where the problem is. + +Let's write a test. When we create a store, we'll use `localVue` to avoid polluting the Vue base constructor. The test creates a store using the store-config.js export: + +```js +import mutations from './mutations' +import getters from './getters' + +export default { + state: { + count: 0 + }, + mutations, + getters +} +``` + +```js +// store-config.spec.js + +import { createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import storeConfig from './store-config' +import { cloneDeep } from 'lodash' + +test('increments count value when increment is commited', () => { + const localVue = createLocalVue() + localVue.use(Vuex) + const store = new Vuex.Store(cloneDeep(storeConfig)) + expect(store.state.count).toBe(0) + store.commit('increment') + expect(store.state.count).toBe(1) +}) + +test('updates evenOrOdd getter when increment is commited', () => { + const localVue = createLocalVue() + localVue.use(Vuex) + const store = new Vuex.Store(cloneDeep(storeConfig)) + expect(store.getters.evenOrOdd).toBe('even') + store.commit('increment') + expect(store.getters.evenOrOdd).toBe('odd') +}) +``` + +Notice that we use `cloneDeep` to clone the store config before creating a store with it. This is because Vuex mutates the options object used to create the store. To make sure we have a clean store in each test, we need to clone the `storeConfig` object. + ### 相关资料 -- [该设置的示例工程](https://github.com/eddyerburgh/vue-test-utils-vuex-example) +- [Example project for testing the components](https://github.com/eddyerburgh/vue-test-utils-vuex-example) +- [Example project for testing the store](https://github.com/eddyerburgh/testing-vuex-store-example) - [`localVue`](../api/options.md#localvue) - [`createLocalVue`](../api/createLocalVue.md) From 73c90e54a6ceab5164d1418c13b3c8ed549a3120 Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Sun, 4 Feb 2018 00:28:02 +0800 Subject: [PATCH 2/2] [docs][zh-cn] translated the parts about vuex store and karma --- docs/zh-cn/guides/testing-SFCs-with-karma.md | 62 ++++++++++---------- docs/zh-cn/guides/using-with-vuex.md | 34 +++++------ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/zh-cn/guides/testing-SFCs-with-karma.md b/docs/zh-cn/guides/testing-SFCs-with-karma.md index d8d8b2b15..e8232e7bb 100644 --- a/docs/zh-cn/guides/testing-SFCs-with-karma.md +++ b/docs/zh-cn/guides/testing-SFCs-with-karma.md @@ -1,20 +1,20 @@ -# Testing Single File Components with Karma +# 用 Karma 测试单文件组件 -> An example project for this setup is available on [GitHub](https://github.com/eddyerburgh/vue-test-utils-karma-example). +> 我们在 [GitHub](https://github.com/eddyerburgh/vue-test-utils-karma-example) 上放有一个该设置的示例工程。 -Karma is a test runner that launches browsers, runs tests, and reports them back to us. We're going to use the Mocha framework to write the tests. We'll use the chai library for test assertions. +Karma 是一个启动浏览器运行测试并生成报告的测试运行器。我们会使用 Mocha 框架撰写测试,同时使用 chai 作为断言库。 -## Setting up Mocha +## 设置 Mocha -We will assume you are starting with a setup that already has webpack, vue-loader and Babel properly configured - e.g. the `webpack-simple` template scaffolded by `vue-cli`. +我们会假设你一开始已经正确配置好了 webpack、vue-loader 和 Babel——例如通过 `vue-cli` 的 `webpack-simple` 模板搭建起来。 -The first thing to do is install the test dependencies: +第一件要做的事是安装测试依赖: ``` bash npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha karma-sourcemap-loader karma-spec-reporter karma-webpack mocha ``` -Next we need to define a test script in our `package.json`. +接下来我们需要在 `package.json` 定义一个测试脚本。 ```json // package.json @@ -25,11 +25,11 @@ Next we need to define a test script in our `package.json`. } ``` -- The `--single-run` flag tells Karma to run the test suite once. +- `--single-run` 标识告诉了 Karma 一次性运行该测试套件。 -### Karma Configuration +### Karma 配置 -Create a karma.conf.js file in the index of the project: +在项目的主目录创建一个 `karma.conf.js` 文件: ```js // karma.conf.js @@ -57,25 +57,25 @@ module.exports = function (config) { } ``` -This file is used to configure Karma. +这个文件用来配置 Karma。 -We need to preprocess our files with webpack. to do that, we add webpack as a preprocessor, and include our webpack config. We can use the webpack config file in the base of the project without changing anything. +我们需要用 webpack 预处理文件。为此,我们将 webpack 添加为预处理器,并引入我们的 webpack 配置。我们可以在项目基础中使用该 webpack 配置文件而无需任何修改。 -In our configuration, we run the tests in Chrome. To add extra browsers, see [the Browsers section in the Karma docs](http://karma-runner.github.io/2.0/config/browsers.html). +在我们的配置中,我们在 Chrome 中运行测试。如果想添加其它浏览器,可查阅[Karma 文档的浏览器章节](http://karma-runner.github.io/2.0/config/browsers.html)。 -### Picking an Assertion Library +### 选用一个断言库 -[Chai](http://chaijs.com/) is a popular assertion library that is commonly used alongside Mocha. You may also want to check out [Sinon](http://sinonjs.org/) for creating spies and stubs. +[Chai](http://chaijs.com/) 是一个流行的常配合 Mocha 使用的断言库。你也可以选用 [Sinon](http://sinonjs.org/) 来创建监视和存根。 -We can install the `karma-chai` plugin to use `chai` in our tests. +我们可以安装 `karma-chai` 插件以在我们的测试中使用 `chai`。 ``` bash npm install --save-dev karma-chai ``` -### Adding a test +### 添加一个测试 -Create a file in `src` named `Counter.vue`: +在 `src` 中创建一个名为 `Counter.vue` 的文件: ``` html