From 20e94d73dd94a21b9f429534e3e3b1b45a461319 Mon Sep 17 00:00:00 2001 From: Alex-Sokolov Date: Sat, 14 Oct 2017 13:03:26 +0300 Subject: [PATCH 01/75] =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D0=BF=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20en=20->=20ru?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/LANGS.md | 1 + docs/ru/README.md | 49 ++++ docs/ru/SUMMARY.md | 61 ++++ docs/ru/api/README.md | 49 ++++ docs/ru/api/createLocalVue.md | 28 ++ docs/ru/api/mount.md | 136 +++++++++ docs/ru/api/options.md | 165 +++++++++++ docs/ru/api/selectors.md | 43 +++ docs/ru/api/shallow.md | 124 ++++++++ docs/ru/api/wrapper-array/README.md | 11 + docs/ru/api/wrapper-array/at.md | 21 ++ docs/ru/api/wrapper-array/contains.md | 24 ++ docs/ru/api/wrapper-array/hasAttribute.md | 21 ++ docs/ru/api/wrapper-array/hasClass.md | 20 ++ docs/ru/api/wrapper-array/hasProp.md | 24 ++ docs/ru/api/wrapper-array/hasStyle.md | 24 ++ docs/ru/api/wrapper-array/is.md | 20 ++ docs/ru/api/wrapper-array/isEmpty.md | 17 ++ docs/ru/api/wrapper-array/isVueInstance.md | 18 ++ docs/ru/api/wrapper-array/setData.md | 22 ++ docs/ru/api/wrapper-array/setMethods.md | 27 ++ docs/ru/api/wrapper-array/setProps.md | 22 ++ docs/ru/api/wrapper-array/trigger.md | 26 ++ docs/ru/api/wrapper-array/update.md | 20 ++ docs/ru/api/wrapper/README.md | 16 ++ docs/ru/api/wrapper/contains.md | 23 ++ docs/ru/api/wrapper/emitted.md | 33 +++ docs/ru/api/wrapper/emittedByOrder.md | 28 ++ docs/ru/api/wrapper/exists.md | 21 ++ docs/ru/api/wrapper/find.md | 27 ++ docs/ru/api/wrapper/findAll.md | 27 ++ docs/ru/api/wrapper/hasAttribute.md | 37 +++ docs/ru/api/wrapper/hasClass.md | 21 ++ docs/ru/api/wrapper/hasProp.md | 25 ++ docs/ru/api/wrapper/hasStyle.md | 24 ++ docs/ru/api/wrapper/html.md | 16 ++ docs/ru/api/wrapper/is.md | 19 ++ docs/ru/api/wrapper/isEmpty.md | 16 ++ docs/ru/api/wrapper/isVueInstance.md | 16 ++ docs/ru/api/wrapper/name.md | 18 ++ docs/ru/api/wrapper/setData.md | 20 ++ docs/ru/api/wrapper/setMethods.md | 24 ++ docs/ru/api/wrapper/setProps.md | 20 ++ docs/ru/api/wrapper/text.md | 16 ++ docs/ru/api/wrapper/trigger.md | 38 +++ docs/ru/api/wrapper/update.md | 19 ++ docs/ru/guides/README.md | 9 + docs/ru/guides/choosing-a-test-runner.md | 45 +++ docs/ru/guides/common-tips.md | 135 +++++++++ docs/ru/guides/getting-started.md | 116 ++++++++ docs/ru/guides/testing-SFCs-with-jest.md | 178 ++++++++++++ .../guides/testing-SFCs-with-mocha-webpack.md | 180 ++++++++++++ docs/ru/guides/using-with-vue-router.md | 71 +++++ docs/ru/guides/using-with-vuex.md | 264 ++++++++++++++++++ 54 files changed, 2475 insertions(+) create mode 100644 docs/ru/README.md create mode 100644 docs/ru/SUMMARY.md create mode 100644 docs/ru/api/README.md create mode 100644 docs/ru/api/createLocalVue.md create mode 100644 docs/ru/api/mount.md create mode 100644 docs/ru/api/options.md create mode 100644 docs/ru/api/selectors.md create mode 100644 docs/ru/api/shallow.md create mode 100644 docs/ru/api/wrapper-array/README.md create mode 100644 docs/ru/api/wrapper-array/at.md create mode 100644 docs/ru/api/wrapper-array/contains.md create mode 100644 docs/ru/api/wrapper-array/hasAttribute.md create mode 100644 docs/ru/api/wrapper-array/hasClass.md create mode 100644 docs/ru/api/wrapper-array/hasProp.md create mode 100644 docs/ru/api/wrapper-array/hasStyle.md create mode 100644 docs/ru/api/wrapper-array/is.md create mode 100644 docs/ru/api/wrapper-array/isEmpty.md create mode 100644 docs/ru/api/wrapper-array/isVueInstance.md create mode 100644 docs/ru/api/wrapper-array/setData.md create mode 100644 docs/ru/api/wrapper-array/setMethods.md create mode 100644 docs/ru/api/wrapper-array/setProps.md create mode 100644 docs/ru/api/wrapper-array/trigger.md create mode 100644 docs/ru/api/wrapper-array/update.md create mode 100644 docs/ru/api/wrapper/README.md create mode 100644 docs/ru/api/wrapper/contains.md create mode 100644 docs/ru/api/wrapper/emitted.md create mode 100644 docs/ru/api/wrapper/emittedByOrder.md create mode 100644 docs/ru/api/wrapper/exists.md create mode 100644 docs/ru/api/wrapper/find.md create mode 100644 docs/ru/api/wrapper/findAll.md create mode 100644 docs/ru/api/wrapper/hasAttribute.md create mode 100644 docs/ru/api/wrapper/hasClass.md create mode 100644 docs/ru/api/wrapper/hasProp.md create mode 100644 docs/ru/api/wrapper/hasStyle.md create mode 100644 docs/ru/api/wrapper/html.md create mode 100644 docs/ru/api/wrapper/is.md create mode 100644 docs/ru/api/wrapper/isEmpty.md create mode 100644 docs/ru/api/wrapper/isVueInstance.md create mode 100644 docs/ru/api/wrapper/name.md create mode 100644 docs/ru/api/wrapper/setData.md create mode 100644 docs/ru/api/wrapper/setMethods.md create mode 100644 docs/ru/api/wrapper/setProps.md create mode 100644 docs/ru/api/wrapper/text.md create mode 100644 docs/ru/api/wrapper/trigger.md create mode 100644 docs/ru/api/wrapper/update.md create mode 100644 docs/ru/guides/README.md create mode 100644 docs/ru/guides/choosing-a-test-runner.md create mode 100644 docs/ru/guides/common-tips.md create mode 100644 docs/ru/guides/getting-started.md create mode 100644 docs/ru/guides/testing-SFCs-with-jest.md create mode 100644 docs/ru/guides/testing-SFCs-with-mocha-webpack.md create mode 100644 docs/ru/guides/using-with-vue-router.md create mode 100644 docs/ru/guides/using-with-vuex.md diff --git a/docs/LANGS.md b/docs/LANGS.md index 25b60e8a0..f379e75aa 100644 --- a/docs/LANGS.md +++ b/docs/LANGS.md @@ -1 +1,2 @@ * [English](en/) +* [Русский](ru/) diff --git a/docs/ru/README.md b/docs/ru/README.md new file mode 100644 index 000000000..2140a591a --- /dev/null +++ b/docs/ru/README.md @@ -0,0 +1,49 @@ +# vue-test-utils + +`vue-test-utils` is the official unit testing utility library for Vue.js. + +* [Guides](guides/README.md) + * [Getting Started](guides/getting-started.md) + * [Common Tips](guides/common-tips.md) + * [Choosing a test runner](guides/choosing-a-test-runner.md) + * [Testing SFCs with Jest](guides/testing-SFCs-with-jest.md) + * [Testing SFCs with Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) + * [Using with Vue Router](guides/using-with-vue-router.md) + * [Using with Vuex](guides/using-with-vuex.md) +* [API](api/README.md) + * [createLocalVue](api/createLocalVue.md) + * [mount](api/mount.md) + * [shallow](api/shallow.md) + * [Mounting Options](api/options.md) + * [Wrapper](api/wrapper/README.md) + * [contains](api/wrapper/contains.md) + * [find](api/wrapper/find.md) + * [hasAttribute](api/wrapper/hasAttribute.md) + * [hasClass](api/wrapper/hasClass.md) + * [hasProp](api/wrapper/hasProp.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) + * [update](api/wrapper/update.md) + * [setData](api/wrapper/setData.md) + * [setProps](api/wrapper/setProps.md) + * [text](api/wrapper/text.md) + * [trigger](api/wrapper/trigger.md) + * [WrapperArray](api/wrapper-array/README.md) + * [at](api/wrapper-array/at.md) + * [contains](api/wrapper-array/contains.md) + * [hasAttribute](api/wrapper-array/hasAttribute.md) + * [hasClass](api/wrapper-array/hasClass.md) + * [hasProp](api/wrapper-array/hasProp.md) + * [hasStyle](api/wrapper-array/hasStyle.md) + * [is](api/wrapper-array/is.md) + * [isEmpty](api/wrapper-array/isEmpty.md) + * [isVueInstance](api/wrapper-array/isVueInstance.md) + * [update](api/wrapper-array/update.md) + * [setData](api/wrapper-array/setData.md) + * [setProps](api/wrapper-array/setProps.md) + * [trigger](api/wrapper-array/trigger.md) + * [Selectors](api/selectors.md) diff --git a/docs/ru/SUMMARY.md b/docs/ru/SUMMARY.md new file mode 100644 index 000000000..6d5dafcd5 --- /dev/null +++ b/docs/ru/SUMMARY.md @@ -0,0 +1,61 @@ +## Table of Contents + +* [Guides](guides/README.md) + * [Getting Started](guides/getting-started.md) + * [Common Tips](guides/common-tips.md) + * [Choosing a test runner](guides/choosing-a-test-runner.md) + * [Testing SFCs with Jest](guides/testing-SFCs-with-jest.md) + * [Testing SFCs with Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) + * [Using with Vue Router](guides/using-with-vue-router.md) + * [Using with Vuex](guides/using-with-vuex.md) +* [API](api/README.md) + * [mount](api/mount.md) + * [shallow](api/shallow.md) + * [Mounting Options](api/options.md) + - [context](api/options.md#context) + - [slots](api/options.md#slots) + - [stubs](api/options.md#stubs) + - [mocks](api/options.md#mocks) + - [localVue](api/options.md#localvue) + - [attachToDocument](api/options.md#attachtodocument) + - [attrs](api/options.md#attrs) + - [listeners](api/options.md#listeners) + - [clone](api/options.md#clone) + * [Wrapper](api/wrapper/README.md) + * [contains](api/wrapper/contains.md) + * [emitted](api/wrapper/emitted.md) + * [emittedByOrder](api/wrapper/emittedByOrder.md) + * [find](api/wrapper/find.md) + * [findAll](api/wrapper/findAll.md) + * [hasAttribute](api/wrapper/hasAttribute.md) + * [hasClass](api/wrapper/hasClass.md) + * [hasProp](api/wrapper/hasProp.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) + * [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) + * [WrapperArray](api/wrapper-array/README.md) + * [at](api/wrapper-array/at.md) + * [contains](api/wrapper-array/contains.md) + * [hasAttribute](api/wrapper-array/hasAttribute.md) + * [hasClass](api/wrapper-array/hasClass.md) + * [hasProp](api/wrapper-array/hasProp.md) + * [hasStyle](api/wrapper-array/hasStyle.md) + * [is](api/wrapper-array/is.md) + * [isEmpty](api/wrapper-array/isEmpty.md) + * [isVueInstance](api/wrapper-array/isVueInstance.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) + * [Selectors](api/selectors.md) + * [createLocalVue](api/createLocalVue.md) diff --git a/docs/ru/api/README.md b/docs/ru/api/README.md new file mode 100644 index 000000000..231254061 --- /dev/null +++ b/docs/ru/api/README.md @@ -0,0 +1,49 @@ +# API + +* [mount](./mount.md) +* [shallow](./shallow.md) +* [Mounting Options](./options.md) + - [context](./options.md#context) + - [slots](./options.md#slots) + - [stubs](./options.md#stubs) + - [mocks](./options.md#mocks) + - [localVue](./options.md#localvue) + - [attachToDocument](./options.md#attachtodocument) + - [attrs](./options.md#attrs) + - [listeners](./options.md#listeners) + - [clone](./options.md#clone) +* [Wrapper](./wrapper/README.md) + * [contains](./wrapper/contains.md) + * [emitted](./wrapper/emitted.md) + * [emittedByOrder](./wrapper/emittedByOrder.md) + * [find](./wrapper/find.md) + * [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) + * [update](./wrapper/update.md) + * [setData](./wrapper/setData.md) + * [setProps](./wrapper/setProps.md) + * [text](./wrapper/text.md) + * [trigger](./wrapper/trigger.md) +* [WrapperArray](./wrapper-array/README.md) + * [at](./wrapper-array/at.md) + * [contains](./wrapper-array/contains.md) + * [hasAttribute](./wrapper-array/hasAttribute.md) + * [hasClass](./wrapper-array/hasClass.md) + * [hasProp](./wrapper-array/hasProp.md) + * [hasStyle](./wrapper-array/hasStyle.md) + * [is](./wrapper-array/is.md) + * [isEmpty](./wrapper-array/isEmpty.md) + * [isVueInstance](./wrapper-array/isVueInstance.md) + * [update](./wrapper-array/update.md) + * [setData](./wrapper-array/setData.md) + * [setProps](./wrapper-array/setProps.md) + * [trigger](./wrapper-array/trigger.md) +* [createLocalVue](./createLocalVue.md) +* [Selectors](./selectors.md) diff --git a/docs/ru/api/createLocalVue.md b/docs/ru/api/createLocalVue.md new file mode 100644 index 000000000..a3cbfcee3 --- /dev/null +++ b/docs/ru/api/createLocalVue.md @@ -0,0 +1,28 @@ +# createLocalVue() + +- **Returns:** + - `{Component}` + +- **Usage:** + +`createLocalVue` returns a Vue class for you to add components, mixins and install plugins without polluting the global Vue class. + +Use it with `options.localVue` + +```js +import { createLocalVue, shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const localVue = createLocalVue() +const wrapper = shallow(Foo, { + localVue, + mocks: { foo: true } +}) +expect(wrapper.vm.foo).toBe(true) + +const freshWrapper = shallow(Foo) +expect(freshWrapper.vm.foo).toBe(false) +``` + +- **See also:** [Common Tips](../guides/common-tips.md#applying-global-plugins-and-mixins) diff --git a/docs/ru/api/mount.md b/docs/ru/api/mount.md new file mode 100644 index 000000000..aaddd3e2f --- /dev/null +++ b/docs/ru/api/mount.md @@ -0,0 +1,136 @@ +# mount(component {, options}]) + +- **Arguments:** + + - `{Component} component` + - `{Object} options` + +- **Returns:** `{Wrapper}` + +- **Options:** + +See [options](options.md) + +- **Usage:** + +Returns [`Wrapper`](wrapper/README.md) of first DOM node or Vue component matching selector. + +Use any valid [selector](selectors.md). + +**Without options:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = mount(Foo) + expect(wrapper.contains('div')).toBe(true) + }) +}) +``` +**With Vue options:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = mount(Foo, { + propsData: { + color: 'red' + } + }) + expect(wrapper.hasProp('color', 'red')).toBe(true) + }) +}) +``` + +**Attach to DOM:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = mount(Foo, { + attachToDocument: true + }) + expect(wrapper.contains('div')).toBe(true) + }) +}) +``` +**Default and named slots:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' +import FooBar from './FooBar.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = mount(Foo, { + slots: { + default: [Bar, FooBar], + fooBar: FooBar, // Will match , + foo: '
' + } + }) + expect(wrapper.contains('div')).toBe(true) + }) +}) +``` + +**Stubbing global properties:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const $route = { path: 'http://www.example-path.com' } + const wrapper = mount(Foo, { + mocks: { + $route + } + }) + expect(wrapper.vm.$route.path).toBe($route.path) + }) +}) +``` + +**Stubbing components:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' +import Faz from './Faz.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = mount(Foo, { + stub: { + Bar: '
, + foo: '
' + } +}) +expect(wrapper.find('div')).toBe(true) +``` + +### `stubs` + +- type: `{ [name: string]: Component | boolean } | Array` + +Stubs child components. Can be an Array of component names to stub, or an object. + +Example: + +```js +import Foo from './Foo.vue' + +mount(Component, { + stubs: ['registered-component'] +}) + +shallow(Component, { + stubs: { + // stub with a specific implementation + 'registered-component': Foo, + // create default stub + 'another-component': true + } +}) +``` + +### `mocks` + +- type: `Object` + +Add additional properties to the instance. Useful for mocking global injections. + +Example: + +```js +import { expect } from 'chai' + +const $route = { path: 'http://www.example-path.com' } +const wrapper = shallow(Component, { + mocks: { + $route + } +}) +expect(wrapper.vm.$route.path).toBe($route.path) +``` + +### `localVue` + +- type: `Vue` + +A local copy of Vue created by [createLocalVue](./createLocalVue.md) to use when mounting the component. Installing plugins on this copy of Vue prevents polluting the original `Vue` copy. + +Example: + +```js +import { createLocalVue, mount } from 'vue-test-utils' +import VueRouter from 'vue-router' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const localVue = createLocalVue() +localVue.use(VueRouter) + +const routes = [ + { path: '/foo', component: Foo } +] + +const router = new VueRouter({ + routes +}) + +const wrapper = mount(Component, { + localVue, + router +}) +expect(wrapper.vm.$route).toBeInstanceOf(Object) +``` + +### `attachToDocument` + +- type: `boolean` +- default: `false` + +Component will be attach to DOM when rendered if set to `true`. This can be used with [`hasStyle`](wrapper/hasStyle.md) to check multi element CSS selectors. + +### `attrs` + +- type: `Object` + +Set the component instance's `$attrs` object. + +### `listeners` + +- type: `Object` + +Set the component instance's `$listeners` object. + +### `clone` + +- type: `boolean` +- default: `true` + +Clones component before mounting if `true`, which avoids mutating the original component definition. + +`options.mocks` (`Object`): Add globals to Vue instance. + +`options.localVue` (`Object`): vue class to use in `mount`. See [createLocalVue](createLocalVue.md) diff --git a/docs/ru/api/selectors.md b/docs/ru/api/selectors.md new file mode 100644 index 000000000..0c6a47f3b --- /dev/null +++ b/docs/ru/api/selectors.md @@ -0,0 +1,43 @@ +# Selectors + +A lot of methods take a selector as an argument. A selector can either be a CSS selector, or a Vue component. + +## CSS Selectors + +mount handles any valid CSS selector: + +- tag selectors (div, foo, bar) +- class selectors (.foo, .bar) +- attribute selectors ([foo], [foo="bar"]) +- id selectors (#foo, #bar) +- pseudo selectors (div:first-of-type) + +You can also use combinators: + +- direct descendant combinator (div > #bar > .foo) +- general descendant combinator (div #bar .foo) +- adjacent sibling selector (div + .foo) +- general sibling selector (div ~ .foo) + +## Vue Components + +Vue components are also valid selectors. + +vue-test-utils uses the `name` property to search the instance tree for matching Vue components. + +```js +// Foo.vue + +export default{ + name: 'FooComponent' +} +``` + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = shallow(Foo) +expect(wrapper.is(Foo)).toBe(true) +``` diff --git a/docs/ru/api/shallow.md b/docs/ru/api/shallow.md new file mode 100644 index 000000000..fa16e9d24 --- /dev/null +++ b/docs/ru/api/shallow.md @@ -0,0 +1,124 @@ +# shallow(component {, options}]) + +- **Arguments:** + + - `{Component} component` + - `{Object} options` + - `{boolean} attachToDocument` + - `{Object} context` + - `{Object} slots` + - `{Array|Component|String} default` + - `{Array|Component|String} named` + - `{Object} mocks` + - `{Object|Array} stubs` + - `{boolean} clone` + - `{Object} children` + - `{Vue} localVue` + +- **Returns:** `{Wrapper}` + +- **Options:** + +See [options](./options.md) + +- **Usage:** + +Returns [`Wrapper`](./wrapper/README.md) of first DOM node or Vue component matching selector. + +Stubs all child components. + +Use any valid [selector](./selectors.md). + +**Without options:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = shallow(Foo) + expect(wrapper.contains('div')).toBe(true) + }) +}) +``` + +**With Vue options:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = shallow(Foo, { + propsData: { + color: 'red' + } + }) + expect(wrapper.hasProp('color', 'red')).toBe(true) + }) +}) +``` + +**Attach to DOM:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = shallow(Foo, { + attachToDocument: true + }) + expect(wrapper.contains('div')).toBe(true) + }) +}) +``` + +**Default and named slots:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' +import FooBar from './FooBar.vue' + +describe('Foo', () => { + it('renders a div', () => { + const wrapper = shallow(Foo, { + slots: { + default: [Bar, FooBar], + fooBar: FooBar, // Will match , + foo: '
' + } + }) + expect(wrapper.find('div')).toBe(true) + }) +}) +``` + +**Stubbing global properties:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const $route = { path: 'http://www.example-path.com' } + const wrapper = shallow(Foo, { + mocks: { + $route + } + }) + expect(wrapper.vm.$route.path).toBe($route.path) + }) +}) +``` diff --git a/docs/ru/api/wrapper-array/README.md b/docs/ru/api/wrapper-array/README.md new file mode 100644 index 000000000..2a6d40ccc --- /dev/null +++ b/docs/ru/api/wrapper-array/README.md @@ -0,0 +1,11 @@ +# WrapperArray + +A `WrapperArray` is an object that contains an array of [Wrappers](../wrapper/README.md), and methods to test the `Wrappers`. + +- **Properties:** + +`length` `number`: the number of `Wrappers` contained in the `WrapperArray` + + - **Methods:** + +There is a detailed list of methods in the WrapperArray section of the docs. diff --git a/docs/ru/api/wrapper-array/at.md b/docs/ru/api/wrapper-array/at.md new file mode 100644 index 000000000..e5864bf1b --- /dev/null +++ b/docs/ru/api/wrapper-array/at.md @@ -0,0 +1,21 @@ +# at(index) + +Returns `Wrapper` at `index` passed. Uses zero based numbering (i.e. first item is at index 0). + +- **Arguments:** + - `{number} index` + +- **Returns:** `{Wrapper}` + +- **Example:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = shallow(Foo) +const divArray = wrapper.findAll('div') +const secondDiv = divArray.at(1) +expect(secondDiv.is('p')).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/contains.md b/docs/ru/api/wrapper-array/contains.md new file mode 100644 index 000000000..3b5ee31de --- /dev/null +++ b/docs/ru/api/wrapper-array/contains.md @@ -0,0 +1,24 @@ +# contains(selector) + +Assert every wrapper in `WrapperArray` contains selector. + +Use any valid [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { shallow } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = shallow(Foo) +const divArray = wrapper.findAll('div') +expect(divArray.contains('p')).toBe(true) +expect(divArray.contains(Bar)).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/hasAttribute.md b/docs/ru/api/wrapper-array/hasAttribute.md new file mode 100644 index 000000000..b3436edc9 --- /dev/null +++ b/docs/ru/api/wrapper-array/hasAttribute.md @@ -0,0 +1,21 @@ +# hasAttribute(attribute, value) + +Assert every `Wrapper` in `WrapperArray` DOM node has `attribute` matching `value`. + +- **Arguments:** + - `{string} attribute` + - `{string} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```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.hasAttribute('id', 'foo')).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/hasClass.md b/docs/ru/api/wrapper-array/hasClass.md new file mode 100644 index 000000000..b4c48b397 --- /dev/null +++ b/docs/ru/api/wrapper-array/hasClass.md @@ -0,0 +1,20 @@ +# hasClass(className) + +Assert every `Wrapper` in `WrapperArray` DOM node has class containing `className`. + +- **Arguments:** + - `{string} className` + +- **Returns:** `{boolean}` + +- **Example:** + +```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.hasClass('bar')).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/hasProp.md b/docs/ru/api/wrapper-array/hasProp.md new file mode 100644 index 000000000..6ce255fd7 --- /dev/null +++ b/docs/ru/api/wrapper-array/hasProp.md @@ -0,0 +1,24 @@ +# hasProp(prop, value) + +Assert every `Wrapper` in `WrapperArray` `vm` has `prop` matching `value`. + +**Note the Wrapper must contain a Vue instance.** + +- **Arguments:** + - `{string} prop` + - `{any} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const barArray = wrapper.findAll(Bar) +expect(barArray.hasProp('bar', 10)).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/hasStyle.md b/docs/ru/api/wrapper-array/hasStyle.md new file mode 100644 index 000000000..fd34608ab --- /dev/null +++ b/docs/ru/api/wrapper-array/hasStyle.md @@ -0,0 +1,24 @@ +# hasStyle(style, value) + +Assert every `Wrapper` in `WrapperArray` DOM node has style matching value. + +Returns `true` if `Wrapper` DOM node has `style` matching `string`. + +**Note will only detect inline styles when running in `jsdom`.** +- **Arguments:** + - `{string} style` + - `{string} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```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/ru/api/wrapper-array/is.md b/docs/ru/api/wrapper-array/is.md new file mode 100644 index 000000000..8a5a7cb7a --- /dev/null +++ b/docs/ru/api/wrapper-array/is.md @@ -0,0 +1,20 @@ +# is(selector) + +Assert every `Wrapper` in `WrapperArray` DOM node or `vm` matches [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +const divArray = wrapper.find('div') +expect(divArray.is('div')).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/isEmpty.md b/docs/ru/api/wrapper-array/isEmpty.md new file mode 100644 index 000000000..6ef8b4145 --- /dev/null +++ b/docs/ru/api/wrapper-array/isEmpty.md @@ -0,0 +1,17 @@ +# isEmpty() + +Assert every `Wrapper` in `WrapperArray` does not contain child node. + +- **Returns:** `{boolean}` + +- **Example:** + +```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.isEmpty()).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/isVueInstance.md b/docs/ru/api/wrapper-array/isVueInstance.md new file mode 100644 index 000000000..66d556b7f --- /dev/null +++ b/docs/ru/api/wrapper-array/isVueInstance.md @@ -0,0 +1,18 @@ +# isVueInstance() + +Assert every `Wrapper` in `WrapperArray` is Vue instance. + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const barArray = wrapper.findAll(Bar) +expect(barArray.isVueInstance()).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/setData.md b/docs/ru/api/wrapper-array/setData.md new file mode 100644 index 000000000..f4f69bf61 --- /dev/null +++ b/docs/ru/api/wrapper-array/setData.md @@ -0,0 +1,22 @@ +# setData(data) + +Sets `Wrapper` `vm` data and forces update on each `Wrapper` in `WrapperArray`. + +**Note every `Wrapper` must contain a Vue instance.** + +- **Arguments:** + - `{Object} data` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const barArray = wrapper.findAll(Bar) +barArray.setData({ foo: 'bar' }) +expect(barArray.at(0).vm.foo).toBe('bar') +``` diff --git a/docs/ru/api/wrapper-array/setMethods.md b/docs/ru/api/wrapper-array/setMethods.md new file mode 100644 index 000000000..5d50927ae --- /dev/null +++ b/docs/ru/api/wrapper-array/setMethods.md @@ -0,0 +1,27 @@ + +# setMethods(methods) + +Sets `Wrapper` `vm` methods and forces update on each `Wrapper` in `WrapperArray`. + +**Note every `Wrapper` must contain a Vue instance.** + +- **Arguments:** + - `{Object} methods` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import sinon from 'sinon' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const barArray = wrapper.findAll(Bar) +const clickMethodStub = sinon.stub() + +barArray.setMethods({ clickMethod: clickMethodStub }) +barArray.at(0).trigger('click') +expect(clickMethodStub.called).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/setProps.md b/docs/ru/api/wrapper-array/setProps.md new file mode 100644 index 000000000..c68e84f1d --- /dev/null +++ b/docs/ru/api/wrapper-array/setProps.md @@ -0,0 +1,22 @@ +# setProps(props) + +Sets `Wrapper` `vm` props and forces update on each `Wrapper` in `WrapperArray`. + +**Note every `Wrapper` must contain a Vue instance.** + +- **Arguments:** + - `{Object} props` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const barArray = wrapper.findAll(Bar) +barArray.setProps({ foo: 'bar' }) +expect(barArray.at(0).vm.foo).toBe('bar') +``` diff --git a/docs/ru/api/wrapper-array/trigger.md b/docs/ru/api/wrapper-array/trigger.md new file mode 100644 index 000000000..5ffdb7423 --- /dev/null +++ b/docs/ru/api/wrapper-array/trigger.md @@ -0,0 +1,26 @@ +# trigger(eventName) + +Triggers an event on every `Wrapper` in the `WrapperArray` DOM node. + +**Note every `Wrapper` must contain a Vue instance.** + +- **Arguments:** + - `{string} eventName` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import sinon from 'sinon' +import Foo from './Foo.vue' + +const clickHandler = sinon.stub() +const wrapper = mount(Foo, { + propsData: { clickHandler } +}) + +const divArray = wrapper.findAll('div') +divArray.trigger('click') +expect(clickHandler.called).toBe(true) +``` diff --git a/docs/ru/api/wrapper-array/update.md b/docs/ru/api/wrapper-array/update.md new file mode 100644 index 000000000..de0647028 --- /dev/null +++ b/docs/ru/api/wrapper-array/update.md @@ -0,0 +1,20 @@ +# update() + +Force root Vue component of each `Wrapper` in `WrapperArray` to re-render. + +If called on a Vue component wrapper array, it will force each Vue component to re-render. + +- **Example:** + +```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.at(0).vm.bar).toBe('bar') +divArray.at(0).vm.bar = 'new value' +divArray.update() +expect(divArray.at(0).vm.bar).toBe('new value') +``` diff --git a/docs/ru/api/wrapper/README.md b/docs/ru/api/wrapper/README.md new file mode 100644 index 000000000..6469b8745 --- /dev/null +++ b/docs/ru/api/wrapper/README.md @@ -0,0 +1,16 @@ +# Wrapper + +vue-test-utils is a wrapper based API. + +A `Wrapper` is an object that contains a mounted component or vnode and methods to test the component or vnode. + +- **Properties:** + +`vm` `Component`: this is the vue instance. You can access all the [instance methods and properties of a vm](https://vuejs.org/v2/api/#Instance-Properties) with `wrapper.vm`. This only exists on Vue component wrappers +`element` `HTMLElement`: the root DOM node of the wrapper +`options` `Object`: Object containing vue-test-utils options passed to `mount` or `shallow` +`options.attachedToDom` `Boolean`: True if attachToDom was passed to `mount` or `shallow` + +- **Methods:** + +There is a detailed list of methods in the wrapper section of the docs. diff --git a/docs/ru/api/wrapper/contains.md b/docs/ru/api/wrapper/contains.md new file mode 100644 index 000000000..a91b0353b --- /dev/null +++ b/docs/ru/api/wrapper/contains.md @@ -0,0 +1,23 @@ +# contains(selector) + +Assert `Wrapper` contains an element or component matching [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +expect(wrapper.contains('p')).toBe(true) +expect(wrapper.contains(Bar)).toBe(true) +``` + +- **See also:** [selectors](../selectors.md) diff --git a/docs/ru/api/wrapper/emitted.md b/docs/ru/api/wrapper/emitted.md new file mode 100644 index 000000000..d754eab98 --- /dev/null +++ b/docs/ru/api/wrapper/emitted.md @@ -0,0 +1,33 @@ +# emitted() + +Return an object containing custom events emitted by the `Wrapper` `vm`. + +- **Returns:** `{ [name: string]: Array> }` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' + +const wrapper = mount(Component) + +wrapper.vm.$emit('foo') +wrapper.vm.$emit('foo', 123) + +/* +wrapper.emitted() returns the following object: +{ + foo: [[], [123]] +} +*/ + +// assert event has been emitted +expect(wrapper.emitted().foo).toBeTruthy() + +// assert event count +expect(wrapper.emitted().foo.length).toBe(2) + +// assert event payload +expect(wrapper.emitted().foo[1]).toEqual([123]) +``` diff --git a/docs/ru/api/wrapper/emittedByOrder.md b/docs/ru/api/wrapper/emittedByOrder.md new file mode 100644 index 000000000..55ff975b2 --- /dev/null +++ b/docs/ru/api/wrapper/emittedByOrder.md @@ -0,0 +1,28 @@ +# emittedByOrder() + +Return an Array containing custom events emitted by the `Wrapper` `vm`. + +- **Returns:** `Array<{ name: string, args: Array }>` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' + +const wrapper = mount(Component) + +wrapper.vm.$emit('foo') +wrapper.vm.$emit('bar', 123) + +/* +wrapper.emittedByOrder() returns the following Array: +[ + { name: 'foo', args: [] }, + { name: 'bar', args: [123] } +] +*/ + +// assert event emit order +expect(wrapper.emittedByOrder().map(e => e.name)).toEqual(['foo', 'bar']) +``` diff --git a/docs/ru/api/wrapper/exists.md b/docs/ru/api/wrapper/exists.md new file mode 100644 index 000000000..4fac1351f --- /dev/null +++ b/docs/ru/api/wrapper/exists.md @@ -0,0 +1,21 @@ +# exists() + +Assert `Wrapper` or `WrapperArray` exists. + +Returns false if called on an empty `Wrapper` or `WrapperArray`. + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.exists()).toBe(true) +expect(wrapper.find('does-not-exist').exists()).toBe(false) +expect(wrapper.findAll('div').exists()).toBe(true) +expect(wrapper.findAll('does-not-exist').exists()).toBe(false) +``` diff --git a/docs/ru/api/wrapper/find.md b/docs/ru/api/wrapper/find.md new file mode 100644 index 000000000..1d121c591 --- /dev/null +++ b/docs/ru/api/wrapper/find.md @@ -0,0 +1,27 @@ +# find(selector) + +Returns [`Wrapper`](README.md) of first DOM node or Vue component matching selector. + +Use any valid [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{Wrapper}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const div = wrapper.find('div') +expect(div.is('div')).toBe(true) +const bar = wrapper.find(Bar) +expect(bar.is(Bar)).toBe(true) +``` + +- **See also:** [Wrapper](README.md) diff --git a/docs/ru/api/wrapper/findAll.md b/docs/ru/api/wrapper/findAll.md new file mode 100644 index 000000000..f78ab6201 --- /dev/null +++ b/docs/ru/api/wrapper/findAll.md @@ -0,0 +1,27 @@ +# findAll(selector) + +Returns a [`WrapperArray`](../wrapper-array/README.md) of [Wrappers](README.md). + +Use any valid [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{WrapperArray}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' + +const wrapper = mount(Foo) +const div = wrapper.findAll('div').at(0) +expect(div.is('div')).toBe(true) +const bar = wrapper.findAll(Bar).at(0) +expect(bar.is(Bar)).toBe(true) +``` + +- **See also:** [Wrapper](README.md) diff --git a/docs/ru/api/wrapper/hasAttribute.md b/docs/ru/api/wrapper/hasAttribute.md new file mode 100644 index 000000000..da9a893b5 --- /dev/null +++ b/docs/ru/api/wrapper/hasAttribute.md @@ -0,0 +1,37 @@ +# hasAttribute(attribute, value) + +Assert `Wrapper` DOM node has attribute matching value. + +Returns `true` if `Wrapper` DOM node contains attribute with matching value. + +- **Arguments:** + - `{string} attribute` + - `{string} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.hasAttribute('id', 'foo')).toBe(true) +``` + +- **Alternative:** + +You could get the attribute from the `Wrapper.element` to have a value based assertion: + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.element.getAttribute('id')).toBe('foo') +``` + +This makes for a more informative assertion error. diff --git a/docs/ru/api/wrapper/hasClass.md b/docs/ru/api/wrapper/hasClass.md new file mode 100644 index 000000000..c70b21ef9 --- /dev/null +++ b/docs/ru/api/wrapper/hasClass.md @@ -0,0 +1,21 @@ +# hasClass(className) + +Assert `Wrapper` DOM node has class contains `className`. + +Returns `true` if `Wrapper` DOM node contains class. + +- **Arguments:** + - `{string} className` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.hasClass('bar')).toBe(true) +``` diff --git a/docs/ru/api/wrapper/hasProp.md b/docs/ru/api/wrapper/hasProp.md new file mode 100644 index 000000000..66e64b41b --- /dev/null +++ b/docs/ru/api/wrapper/hasProp.md @@ -0,0 +1,25 @@ +# hasProp(prop, value) + +Assert `Wrapper` `vm` has `prop` matching `value`. + +Returns `true` if `Wrapper` `vm` has `prop` matching `value`. + + +**Note: the Wrapper must contain a Vue instance.** + +- **Arguments:** + - `{string} prop` + - `{any} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.hasProp('bar', 10)).toBe(true) +``` diff --git a/docs/ru/api/wrapper/hasStyle.md b/docs/ru/api/wrapper/hasStyle.md new file mode 100644 index 000000000..3d3bb68b4 --- /dev/null +++ b/docs/ru/api/wrapper/hasStyle.md @@ -0,0 +1,24 @@ +# hasStyle(style, value) + +Assert `Wrapper` DOM node has style matching value + +Returns `true` if `Wrapper` DOM node has `style` matching `string`. + +**Note will only detect inline styles when running in `jsdom`.** + +- **Arguments:** + - `{string} style` + - `{string} value` + +- **Returns:** `{boolean}` + +- **Example:** + +```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/ru/api/wrapper/html.md b/docs/ru/api/wrapper/html.md new file mode 100644 index 000000000..1243f180f --- /dev/null +++ b/docs/ru/api/wrapper/html.md @@ -0,0 +1,16 @@ +# html() + +Returns HTML of `Wrapper` DOM node as a string. + +- **Returns:** `{string}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.html()).toBe('

Foo

') +``` diff --git a/docs/ru/api/wrapper/is.md b/docs/ru/api/wrapper/is.md new file mode 100644 index 000000000..2987de1a2 --- /dev/null +++ b/docs/ru/api/wrapper/is.md @@ -0,0 +1,19 @@ +# is(selector) + +Assert `Wrapper` DOM node or `vm` matches [selector](../selectors.md). + +- **Arguments:** + - `{string|Component} selector` + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.is('div')).toBe(true) +``` diff --git a/docs/ru/api/wrapper/isEmpty.md b/docs/ru/api/wrapper/isEmpty.md new file mode 100644 index 000000000..d70fe7140 --- /dev/null +++ b/docs/ru/api/wrapper/isEmpty.md @@ -0,0 +1,16 @@ +# isEmpty() + +Assert `Wrapper` does not contain child node. + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.isEmpty()).toBe(true) +``` diff --git a/docs/ru/api/wrapper/isVueInstance.md b/docs/ru/api/wrapper/isVueInstance.md new file mode 100644 index 000000000..9da12a267 --- /dev/null +++ b/docs/ru/api/wrapper/isVueInstance.md @@ -0,0 +1,16 @@ +# isVueInstance() + +Assert `Wrapper` is Vue instance. + +- **Returns:** `{boolean}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.isVueInstance()).toBe(true) + ``` diff --git a/docs/ru/api/wrapper/name.md b/docs/ru/api/wrapper/name.md new file mode 100644 index 000000000..a1faf1b4f --- /dev/null +++ b/docs/ru/api/wrapper/name.md @@ -0,0 +1,18 @@ +# name() + +Returns component name if `Wrapper` contains a Vue instance, or the tag name of `Wrapper` DOM node if `Wrapper` does not contain a Vue instance. + +- **Returns:** `{string}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.name()).toBe('Foo') +const p = wrapper.find('p') +expect(p.name()).toBe('p') +``` diff --git a/docs/ru/api/wrapper/setData.md b/docs/ru/api/wrapper/setData.md new file mode 100644 index 000000000..608f083f4 --- /dev/null +++ b/docs/ru/api/wrapper/setData.md @@ -0,0 +1,20 @@ +# setData(data) + +Sets `Wrapper` `vm` data and forces update. + +**Note the Wrapper must contain a Vue instance.** + +- **Arguments:** + - `{Object} data` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +wrapper.setData({ foo: 'bar' }) +expect(wrapper.vm.foo).toBe('bar') +``` diff --git a/docs/ru/api/wrapper/setMethods.md b/docs/ru/api/wrapper/setMethods.md new file mode 100644 index 000000000..4a40546ee --- /dev/null +++ b/docs/ru/api/wrapper/setMethods.md @@ -0,0 +1,24 @@ +# setMethods(methods) + +Sets `Wrapper` `vm` methods and forces update. + +**Note the Wrapper must contain a Vue instance.** + +- **Arguments:** + - `{Object} methods` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import sinon from 'sinon' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +const clickMethodStub = sinon.stub() + +wrapper.setMethods({ clickMethod: clickMethodStub }) +wrapper.find('button').trigger('click') +expect(clickMethodStub.called).toBe(true) +``` diff --git a/docs/ru/api/wrapper/setProps.md b/docs/ru/api/wrapper/setProps.md new file mode 100644 index 000000000..67ff3f3b1 --- /dev/null +++ b/docs/ru/api/wrapper/setProps.md @@ -0,0 +1,20 @@ +# setProps(props) + +Sets `Wrapper` `vm` props and forces update. + +**Note the Wrapper must contain a Vue instance.** + +- **Arguments:** + - `{Object} props` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +wrapper.setProps({ foo: 'bar' }) +expect(wrapper.props().foo).toBe('bar') +``` diff --git a/docs/ru/api/wrapper/text.md b/docs/ru/api/wrapper/text.md new file mode 100644 index 000000000..d1ccd4b44 --- /dev/null +++ b/docs/ru/api/wrapper/text.md @@ -0,0 +1,16 @@ +# text() + +Returns text content of `Wrapper`. + +- **Returns:** `{string}` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.text()).toBe('bar') +``` diff --git a/docs/ru/api/wrapper/trigger.md b/docs/ru/api/wrapper/trigger.md new file mode 100644 index 000000000..537cda9e6 --- /dev/null +++ b/docs/ru/api/wrapper/trigger.md @@ -0,0 +1,38 @@ +# trigger(eventName) + +Triggers an event on the `Wrapper` DOM node. + +Trigger takes an optional `options` object. The properties in the `options` object are added to the Event. + +You can run preventDefault on the event by passing `preventDefault: true` in `options`. + +- **Arguments:** + - `{string} eventName` + - `{Object} options` + - `{boolean} preventDefault` + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import sinon from 'sinon' +import Foo from './Foo' + +const clickHandler = sinon.stub() +const wrapper = mount(Foo, { + propsData: { clickHandler } +}) + +wrapper.trigger('click') + +wrapper.trigger('click', { + button: 0 +}) + +wrapper.trigger('click', { + preventDefault: true +}) + +expect(clickHandler.called).toBe(true) +``` diff --git a/docs/ru/api/wrapper/update.md b/docs/ru/api/wrapper/update.md new file mode 100644 index 000000000..15d13be89 --- /dev/null +++ b/docs/ru/api/wrapper/update.md @@ -0,0 +1,19 @@ +# update() + +Force root Vue component to re-render. + +If called on a `Wrapper` containing a `vm`, it will force the `Wrapper` `vm` to re-render. + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo) +expect(wrapper.vm.bar).toBe('bar') +wrapper.vm.bar = 'new value' +wrapper.update() +expect(wrapper.vm.bar).toBe('new value') +``` diff --git a/docs/ru/guides/README.md b/docs/ru/guides/README.md new file mode 100644 index 000000000..8e8b6119d --- /dev/null +++ b/docs/ru/guides/README.md @@ -0,0 +1,9 @@ +# Guides + +* [Getting Started](./getting-started.md) +* [Common Tips](./common-tips.md) +* [Choosing a test runner](./choosing-a-test-runner.md) +* [Using with Jest](./using-with-jest.md) +* [Testing SFCs with Jest](./testing-SFCs-with-jest.md) +* [Testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md) +* [Using with Vuex](./using-with-vuex.md) diff --git a/docs/ru/guides/choosing-a-test-runner.md b/docs/ru/guides/choosing-a-test-runner.md new file mode 100644 index 000000000..692264d5d --- /dev/null +++ b/docs/ru/guides/choosing-a-test-runner.md @@ -0,0 +1,45 @@ +# Choosing a test runner + +A test runner is a program that runs tests. + +There are many popular JavaScript test runners, and `vue-test-utils` works with all of them. It's test runner agnostic. + +There are a few things to consider when choosing a test runner though: feature set, performance, and support for single-file component (SFC) pre-compilation. After carefully comparing existing libraries, here are two test runners that we recommend: + +- [Jest](https://facebook.github.io/jest/docs/en/getting-started.html#content) is the most fully featured test runner. It requires the least configuration, sets up JSDOM by default, provides built-in assertions, and has a great command line user experience. However, you will need a preprocessor to be able to import SFC components in your tests. We have created the `jest-vue` preprocessor which can handle most common SFC features, but it currently does not have 100% feature parity with `vue-loader`. + +- [mocha-webpack](https://github.com/zinserjan/mocha-webpack) is a wrapper around webpack + Mocha, but with a more streamlined interface and watch mode. The benefits of this setup is that we can get complete SFC support via webpack + `vue-loader`, but it requires more configuration upfront. + +## Browser Environment + +`vue-test-utils` relies on a browser environment. Technically you can run it in a real browser, but it's not recommended due to the complexity of launching real browsers on different platforms. Instead, we recommend running the tests in Node.js with a virtual browser environment using [JSDOM](https://github.com/tmpvar/jsdom). + +The Jest test runner sets up JSDOM automatically. For other test runners, you can manually set up JSDOM for the tests using [jsdom-global](https://github.com/rstacruz/jsdom-global) in the entry for your tests: + +``` bash +npm install --save-dev jsdom jsdom-global +``` +--- +``` js +// in test setup / entry +require('jsdom-global')() +``` + +## Testing Single-File Components + +Single-file Vue components (SFCs) require pre-compilation before they can be run in Node or in the browser. There are two recommended ways to perform the compilation: with a Jest preprocessor, or directly use webpack. + +The `jest-vue` preprocessor supports basic SFC functionalities, but currently does not handle style blocks or custom blocks, which are only supported in `vue-loader`. If you rely on these features or other webpack-specific configurations, you will need to use a webpack + `vue-loader` based setup. + +Read the following guides for different setups: + +- [Testing SFCs with Jest](./testing-SFCs-with-jest.md) +- [Testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md) + +## Resources + +- [Test runner performance comparison](https://github.com/eddyerburgh/vue-unit-test-perf-comparison) +- [Example project with Jest](https://github.com/vuejs/vue-test-utils-jest-example) +- [Example project with Mocha](https://github.com/vuejs/vue-test-utils-mocha-webpack-example) +- [Example project with tape](https://github.com/eddyerburgh/vue-test-utils-tape-example) +- [Example project with AVA](https://github.com/eddyerburgh/vue-test-utils-ava-example) diff --git a/docs/ru/guides/common-tips.md b/docs/ru/guides/common-tips.md new file mode 100644 index 000000000..abd7500a7 --- /dev/null +++ b/docs/ru/guides/common-tips.md @@ -0,0 +1,135 @@ +# Common Tips + +## Knowing What to Test + +For UI components, we don't recommend aiming for complete line-based coverage, because it leads to too much focus on the internal implementation details of the components and could result in brittle tests. + +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). + +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. + +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. + +This topic is discussed with more details in a [great presentation by Matt O'Connell](http://slides.com/mattoconnell/deck#/). + +## Shallow Rendering + +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. + +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. + +`vue-test-utils` allows you to mount a component without rendering its child components (by stubbing them) with the `shallow` method: + +```js +import { shallow } from 'vue-test-utils' + +const wrapper = shallow(Component) // returns a Wrapper containing a mounted Component instance +wrapper.vm // the mounted Vue instance +``` + +## Asserting Emitted Events + +Each mounted wrapper automatically records all events emitted by the underlying Vue instance. You can retrieve the recorded events using the `wrapper.emitted()` method: + +``` js +wrapper.vm.$emit('foo') +wrapper.vm.$emit('foo', 123) + +/* +wrapper.emitted() returns the following object: +{ + foo: [[], [123]] +} +*/ +``` + +You can then make assertions based on these data: + +``` js +import { expect } from 'chai' + +// assert event has been emitted +expect(wrapper.emitted().foo).toBeTruthy() + +// assert event count +expect(wrapper.emitted().foo.length).toBe(2) + +// assert event payload +expect(wrapper.emitted().foo[1]).toEqual([123]) +``` + +You can also get an Array of the events in their emit order by calling [wrapper.emittedByOrder()](../api/wrapper/emittedByOrder.md). + +## Manipulating Component State + +You can directly manipulate the state of the component using the `setData` or `setProps` method on the wrapper: + +```js +wrapper.setData({ count: 10 }) + +wrapper.setProps({ foo: 'bar' }) +``` + +## Mocking Props + +You can pass props to the component using Vue's built-in `propsData` option: + +```js +import { mount } from 'vue-test-utils' + +mount(Component, { + propsData: { + aProp: 'some value' + } +}) +``` + +You can also update the props of an already-mounted component with the `wrapper.setProps({})` method. + +*For a full list of options, please see the [mount options section](../api/options.md) of the docs.* + +## Applying Global Plugins and Mixins + +Some of the components may rely on features injected by a global plugin or mixin, for example `vuex` and `vue-router`. + +If you are writing tests for components in a specific app, you can setup the same global plugins and mixins once in the entry of your tests. But in some cases, for example testing a generic component suite that may get shared across different apps, it's better to test your components in a more isolated setup, without polluting the global `Vue` constructor. We can use the [createLocalVue](../api/createLocalVue.md) method to achieve that: + +``` js +import createLocalVue from 'vue-test-utils' + +// create an extended Vue constructor +const localVue = createLocalVue() + +// install plugins as normal +localVue.use(MyPlugin) + +// pass the localVue to the mount options +mount(Component, { + localVue +}) +``` + +## Mocking Injections + +Another strategy for injected properties is simply mocking them. You can do that with the `mocks` option: + +```js +import { mount } from 'vue-test-utils' + +const $route = { + path: '/', + hash: '', + params: { id: '123' }, + query: { q: 'hello' } +} + +mount(Component, { + mocks: { + $route // adds the mocked $route object to the Vue instance before mounting component + } +}) +``` + +## Dealing with Routing + +Since routing by definition has to do with the overall structure of the application and involves multiple components, it is best tested via integration or end-to-end tests. For individual components that rely on `vue-router` features, you can mock them using the techniques mentioned above. diff --git a/docs/ru/guides/getting-started.md b/docs/ru/guides/getting-started.md new file mode 100644 index 000000000..5c023d6dc --- /dev/null +++ b/docs/ru/guides/getting-started.md @@ -0,0 +1,116 @@ +# Getting Started + +## Setup + +To get a quick taste of using `vue-test-utils`, clone our demo repository with basic setup and install the dependencies: + +``` bash +git clone https://github.com/vuejs/vue-test-utils-getting-started +cd vue-test-utils-getting-started +npm install +``` + +You will see that the project includes a simple component, `counter.js`: + +```js +// counter.js + +export default { + template: ` +
+ {{ count }} + +
+ `, + + data () { + return { + count: 0 + } + }, + + methods: { + increment () { + this.count++ + } + } +} +``` + +### Mounting Components + +`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). + +Mounted components are returned inside a [Wrapper](./api/wrapper.md), which exposes many convenience methods for manipulating, traversing and querying the underlying Vue component instance. + +You can create wrappers using the `mount` method. Let's create a file called `test.js`: + +```js +// test.js + +// Import the mount() method from the test utils +// and the component you want to test +import { mount } from 'vue-test-utils' +import Counter from './counter' + +// Now mount the component and you have the wrapper +const wrapper = mount(Counter) + +// You can access the actual Vue instance via wrapper.vm +const vm = wrapper.vm + +// To inspect the wrapper deeper just log it to the console +// and your adventure with the vue-test-utils begins +console.log(wrapper) +``` + +### Test rendered HTML output of the component + +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. + +```js +import { mount } from 'vue-test-utils' +import Counter from './counter' + +describe('Counter', () => { + // Now mount the component and you have the wrapper + const wrapper = mount(Counter) + + it('renders the correct markup', () => { + expect(wrapper.html()).toContain('0') + }) + + // it's also easy to check for the existence of elements + it('has a button', () => { + expect(wrapper.contains('button')).toBe(true) + }) +}) +``` + +Now run the tests with `npm test`. You should see the tests passing. + +### Simulating User Interaction + +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: + +```js +it('button click should increment the count', () => { + expect(wrapper.vm.count).toBe(0) + const button = wrapper.find('button') + button.trigger('click') + expect(wrapper.vm.count).toBe(1) +}) +``` + +### What about `nextTick`? + +Vue batches pending DOM updates and applies them asynchronously to prevent unnecessary re-renders caused by multiple data mutations. This is why in practice we often have to use `Vue.nextTick` to wait until Vue has performed the actual DOM update after we trigger some state change. + +To simplify usage, `vue-test-utils` applies all updates synchronously so you don't need to use `Vue.nextTick` to wait for DOM updates in your tests. + +*Note: `nextTick` is still necessary when you need to explictly advance the event loop, for operations such as asynchronous callbacks or promise resolution.* + +## What's Next + +- Integrate `vue-test-utils` into your project by [choosing a test runner](./choosing-a-test-runner.md) +- Learn more about [common techniques when writing tests](./common-tips.md) diff --git a/docs/ru/guides/testing-SFCs-with-jest.md b/docs/ru/guides/testing-SFCs-with-jest.md new file mode 100644 index 000000000..0bd70718d --- /dev/null +++ b/docs/ru/guides/testing-SFCs-with-jest.md @@ -0,0 +1,178 @@ +# Testing Single File Components with Jest + +> An example project for this setup is available on [GitHub](https://github.com/vuejs/vue-test-utils-jest-example). + +Jest is a test runner developed by Facebook, aiming to deliver a battery-included unit testing solution. You can learn more about Jest on its [official documentation](https://facebook.github.io/jest/). + +## Setting up Jest + +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 Jest and `vue-test-utils`: + +```bash +$ npm install --save-dev jest vue-test-utils +``` + +Next we need to define a unit script in our `package.json`. + +```json +// package.json +{ + "scripts": { + "test": "jest" + } +} +``` + +## Processing SFCs in Jest + +To teach Jest how to process `*.vue` files, we will need to install and configure the `jest-vue` preprocessor: + +``` bash +npm install --save-dev jest-vue +``` + +Next, create a `jest` block in `package.json`: + +``` json +{ + // ... + "jest": { + "moduleFileExtensions": [ + "js", + "json", + // tell Jest to handle *.vue files + "vue" + ], + "transform": { + // process *.vue files with jest-vue + ".*\\.(vue)$": "/node_modules/jest-vue" + }, + "mapCoverage": true + } +} +``` + +> **Note:** `jest-vue` currently does not support all the features of `vue-loader`, for example custom block support and style loading. In addition, some webpack-specific features such as code-splitting are not supported either. To use them, read the guide on [testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md). + +## Handling webpack Aliases + +If you use a resolve alias in the webpack config, e.g. aliasing `@` to `/src`, you need to add a matching config for Jest as well, using the `moduleNameMapper` option: + +``` json +{ + // ... + "jest": { + // ... + // support the same @ -> src alias mapping in source code + "moduleNameMapper": { + "^@/(.*)$": "/src/$1" + } + } +} +``` + +## Configuring Babel for Jest + +Although latest versions of Node already supports most ES2015 features, you may still want to use ES modules syntax and stage-x features in your tests. For that we need to install `babel-jest`: + +``` bash +npm install --save-dev babel-jest +``` + +Next, we need to tell Jest to process JavaScript test files with `babel-jest` by adding an entry under `jest.transform` in `package.json`: + +``` json +{ + // ... + "jest": { + // ... + "transform": { + // ... + // process js with babel-jest + "^.+\\.js$": "/node_modules/babel-jest" + }, + // ... + } +} +``` + +> By default, `babel-jest` automatically configures itself as long as it's installed. However, because we have explicitly added a transform for `*.vue` files, we now need to explicitly configure `babel-jest` as well. + +Assuming using `babel-preset-env` with webpack, the default Babel config disables ES modules transpilation because webpack already knows how to handle ES modules. However, we do need to enable it for our tests because Jest tests run directly in Node. + +Also, we can tell `babel-preset-env` to target the Node version we are using. This skips transpiling unnecessary features and makes our tests boot faster. + +To apply these options only for tests, put them in a separate config under `env.test` (this will be automatically picked up by `babel-jest`). + +Example `.babelrc`: + +``` json +{ + "presets": [ + ["env", { "modules": false }] + ], + "env": { + "test": { + "presets": [ + ["env", { "targets": { "node": "current" }}] + ] + } + } +} +``` + +### Snapshot Testing + +You can use [`vue-server-renderer`](https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer) to render a component into a string so that it can be saved as a snapshot for [Jest snapshot testing](https://facebook.github.io/jest/docs/en/snapshot-testing.html). + +The render result of `vue-server-renderer` includes a few SSR-specific attributes, and it ignores whitespaces, making it harder to scan a diff. We can improve the saved snapshot with a custom serializer: + +``` bash +npm install --save-dev jest-serializer-vue +``` + +Then configure it in `package.json`: + +``` json +{ + // ... + "jest": { + // ... + // serializer for snapshots + "snapshotSerializers": [ + "/node_modules/jest-serializer-vue" + ] + } +} +``` + +### Placing Test Files + +By default, jest will recursively pick up all files that have a `.spec.js` or `.test.js` extension in the entire project. If this does not fit your needs, it's possible [to change the testRegex](https://facebook.github.io/jest/docs/en/configuration.html#testregex-string) in the config section in the `package.json` file. + +Jest recommends creating a `__tests__` directory right next to the code being tested, but feel free to structure your tests as you see fit. Just beware that Jest would create a `__snapshots__` directory next to test files that performs snapshot testing. + +### Example Spec + +If you are familiar with Jasmine, you should feel right at home with Jest's [assertion API](https://facebook.github.io/jest/docs/en/expect.html#content): + +```js +import { mount } from 'vue-test-utils' +import Component from './component' + +describe('Component', () => { + test('is a Vue instance', () => { + const wrapper = mount(Component) + expect(wrapper.isVueInstance()).toBeTruthy() + }) +}) +``` + +### Resources + +- [Example project for this setup](https://github.com/vuejs/vue-test-utils-jest-example) +- [Examples and slides from Vue Conf 2017](https://github.com/codebryo/vue-testing-with-jest-conf17) +- [Jest](https://facebook.github.io/jest/) +- [Babel preset env](https://github.com/babel/babel-preset-env) diff --git a/docs/ru/guides/testing-SFCs-with-mocha-webpack.md b/docs/ru/guides/testing-SFCs-with-mocha-webpack.md new file mode 100644 index 000000000..f7013a015 --- /dev/null +++ b/docs/ru/guides/testing-SFCs-with-mocha-webpack.md @@ -0,0 +1,180 @@ +# Testing Single File Components with Mocha + webpack + +> An example project for this setup is available on [GitHub](https://github.com/vuejs/vue-test-utils-mocha-webpack-example). + +Another strategy for testing SFCs is compiling all our tests via webpack and then run it in a test runner. The advantage of this approach is that it gives us full support for all webpack and `vue-loader` features, so we don't have to make compromises in our source code. + +You can technically use any test runner you like and manually wire things together, but we've found [`mocha-webpack`](https://github.com/zinserjan/mocha-webpack) to provide a very streamlined experience for this particular task. + +## Setting Up `mocha-webpack` + +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 installing test dependencies: + +``` bash +npm install --save-dev vue-test-utils mocha mocha-webpack +``` + +Next we need to define a test script in our `package.json`. + +```json +// package.json +{ + "scripts": { + "test": "mocha-webpack --webpack-config webpack.config.js --require test/setup.js test/**/*.spec.js" + } +} +``` + +A few things to note here: + +- The `--webpack-config` flag specifies the webpack config file to use for the tests. In most cases, this would be identical to the config you use for the actual project with one small tweak. We will talk about this later. + +- The `--require` flag ensures the file `test/setup.js` is run before any tests, in which we can setup the global environment for our tests to be run in. + +- The final argument is a glob for the test files to be included in the test bundle. + +### Extra webpack Configuration + +#### Externalizing NPM Dependencies + +In our tests we will likely import a number of NPM dependencies - some of these modules may be written without browser usage in mind and simply cannot be bundled properly by webpack. Another consideration is externalizing dependencies greatly improves test boot up speed. We can externalize all NPM dependencies with `webpack-node-externals`: + +```js +// webpack.config.js +const nodeExternals = require('webpack-node-externals') + +module.exports = { + // ... + externals: [nodeExternals()] +} +``` + +#### Source Maps + +Source maps need to be inlined to be picked up by `mocha-webpack`. The recommended config is: + +``` js +module.exports = { + // ... + devtool: 'inline-cheap-module-source-map' +} +``` + +If debugging via IDE, it's also recommended to add the following: + +``` js +module.exports = { + // ... + output: { + // ... + // use absolute paths in sourcemaps (important for debugging via IDE) + devtoolModuleFilenameTemplate: '[absolute-resource-path]', + devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]' + } +} +``` + +### Setting Up Browser Environment + +`vue-test-utils` requires a browser environment to run. We can simulate it in Node.js using `jsdom-global`: + +```bash +npm install --save-dev jsdom jsdom-global +``` + +Then in `test/setup.js`: + +``` js +require('jsdom-global')() +``` + +This adds a browser environment to node, so that `vue-test-utils` can run correctly. + +### 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. + +Alternatively you can use `expect` which is now part of Jest, and exposes [the exact same API](http://facebook.github.io/jest/docs/en/expect.html#content) in Jest docs. + +We will be using `expect` here and make it globally available so that we don't have to import it in every test: + +``` bash +npm install --save-dev expect +``` + +Then in `test/setup.js`: + +``` js +require('jsdom-global')() + +global.expect = require('expect') +``` + +### Optimizing Babel for Tests + +Notice that we are using `babel-loader` to handle JavaScript. You should already have Babel configured if you are using it in your app via a `.babelrc` file. Here `babel-loader` will automatically use the same config file. + +One thing to note is that if you are using Node 6+, which already supports the majority of ES2015 features, you can configure a separate Babel [env option](https://babeljs.io/docs/usage/babelrc/#env-option) that only transpiles features that are not already supported in the Node version you are using (e.g. `stage-2` or flow syntax support, etc.) + +### 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 { 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()).toMatch('1') + }) +}) +``` + +And now we can run the test: + +``` +npm run unit +``` + +Woohoo, we got our tests running! + +### Resources + +- [Example project for this setup](https://github.com/vuejs/vue-test-utils-mocha-webpack-example) +- [Mocha](https://mochajs.org/) +- [mocha-webpack](http://zinserjan.github.io/mocha-webpack/) +- [Chai](http://chaijs.com/) +- [Sinon](http://sinonjs.org/) +- [jest/expect](http://facebook.github.io/jest/docs/en/expect.html#content) diff --git a/docs/ru/guides/using-with-vue-router.md b/docs/ru/guides/using-with-vue-router.md new file mode 100644 index 000000000..d69353af0 --- /dev/null +++ b/docs/ru/guides/using-with-vue-router.md @@ -0,0 +1,71 @@ +# Using with Vue Router + +## Installing Vue Router in tests + +You should never install Vue Router on the Vue base constructor in tests. Installing Vue Router adds `$route` and `$router` as read-only properties on Vue prototype. + +To avoid this, we can create a localVue, and install Vue Router on that. + +```js +import VueRouter from 'vue-router' +const localVue = createLocalVue() + +localVue.use(VueRouter) + +shallow(Component, { + localVue +}) +``` + +## Testing components that use `router-link` or `router-view` + +When you install Vue Router, the `router-link` and `router-view` components are registered. This means we can use them anywhere in our application without needing to import them. + +When we run tests, we need to make these vue-router components available to the component we're mounting. There are two methods to do this. + +### Using stubs + +```js +shallow(Component, { + stubs: ['router-link', 'router-view'] +}) +``` + +### Installing Vue Router with localVue + +```js +import VueRouter from 'vue-router' +const localVue = createLocalVue() + +localVue.use(VueRouter) + +shallow(Component, { + localVue +}) +``` + +## Mocking `$route` and `$router` + +Sometimes you want to test that a component does something with parameters from the `$route` and `$router` objects. To do that, you can pass custom mocks to the Vue instance. + +```js +const $route = { + path: '/some/path' +} + +const wrapper = shallow(Component, { + mocks: { + $route + } +}) + +wrapper.vm.$router // /some/path +``` + +## Common gotchas + +Installing Vue Router adds `$route` and `$router` as read-only properties on Vue prototype. + +This means any future tests that try to mock `$route` or `$router` will fail. + +To avoid this, never install Vue Router when you're running tests. diff --git a/docs/ru/guides/using-with-vuex.md b/docs/ru/guides/using-with-vuex.md new file mode 100644 index 000000000..85f40d7fd --- /dev/null +++ b/docs/ru/guides/using-with-vuex.md @@ -0,0 +1,264 @@ +# Using with Vuex + +In this guide, we'll see how to test Vuex in components with `vue-test-utils`. + +## Mocking Actions + +Let’s look at some code. + +This is the component we want to test. It calls Vuex actions. + +``` html + + + +``` + +For the purposes of this test, we don’t care what the actions do, or what the store looks like. We just need to know that these actions are being fired when they should, and that they are fired with the expected value. + +To test this, we need to pass a mock store to Vue when we shallow our component. + +Instead of passing the store to the base Vue constructor, we can pass it to a - [localVue](../api/options.md#localvue). A localVue is a scoped Vue constructor that we can make changes to without affecting the global Vue constructor. + +Let’s see what this looks like: + +``` js +import { shallow, createLocalVue } from 'vue-test-utils' +import Vuex from 'vuex' +import Actions from '../../../src/components/Actions' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('Actions.vue', () => { + let actions + let store + + beforeEach(() => { + actions = { + actionClick: jest.fn(), + actionInput: jest.fn() + } + store = new Vuex.Store({ + state: {}, + actions + }) + }) + + it('calls store action actionInput when input value is input and an input event is fired', () => { + const wrapper = shallow(Actions, { store, localVue }) + const input = wrapper.find('input') + input.element.value = 'input' + input.trigger('input') + expect(actions.actionInput).toHaveBeenCalled() + }) + + it('does not call store action actionInput when input value is not input and an input event is fired', () => { + const wrapper = shallow(Actions, { store, localVue }) + const input = wrapper.find('input') + input.element.value = 'not input' + input.trigger('input') + expect(actions.actionInput).not.toHaveBeenCalled() + }) + + it('calls store action actionClick when button is clicked', () => { + const wrapper = shallow(Actions, { store, localVue }) + wrapper.find('button').trigger('click') + expect(actions.actionClick).toHaveBeenCalled() + }) +}) +``` + +What’s happening here? First we tell Vue to use Vuex with the `Vue.use` method. This is just a wrapper around `Vue.use`. + +We then make a mock store by calling new `Vuex.store` with our mock values. We only pass it the actions, since that’s all we care about. + +The actions are [jest mock functions](https://facebook.github.io/jest/docs/en/mock-functions.html). These mock functions give us methods to assert whether the actions were called or not. + +We can then assert in our tests that the action stub was called when expected. + +Now the way we define the store might look a bit foreign to you. + +We’re using `beforeEach` to ensure we have a clean store before each test. `beforeEach` is a mocha hook that’s called before each test. In our test, we are reassigning the store variables value. If we didn’t do this, the mock functions would need to be automatically reset. It also lets us change the state in our tests, without it affecting later tests. + +The most important thing to note in this test is that **we create a mock Vuex store and then pass it to vue-test-utils**. + +Great, so now we can mock actions, let’s look at mocking getters. + +## Mocking Getters + + +``` html + + + +``` + +This is a fairly simple component. It renders the result of the getters `clicks` and `inputValue`. Again, we don’t really care about what those getters returns – just that the result of them is being rendered correctly. + +Let’s see the test: + +``` js +import { shallow, createLocalVue } from 'vue-test-utils' +import Vuex from 'vuex' +import Actions from '../../../src/components/Getters' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('Getters.vue', () => { + let getters + let store + + beforeEach(() => { + getters = { + clicks: () => 2, + inputValue: () => 'input' + } + + store = new Vuex.Store({ + getters + }) + }) + + it('Renders state.inputValue in first p tag', () => { + const wrapper = shallow(Actions, { store, localVue }) + const p = wrapper.find('p') + expect(p.text()).toBe(getters.inputValue()) + }) + + it('Renders state.clicks in second p tag', () => { + const wrapper = shallow(Actions, { store, localVue }) + const p = wrapper.findAll('p').at(1) + expect(p.text()).toBe(getters.clicks().toString()) + }) +}) +``` +This test is similar to our actions test. We create a mock store before each test, pass it as an option when we call `shallow`, and assert that the value returned by our mock getters is being rendered. + +This is great, but what if we want to check our getters are returning the correct part of our state? + +## Mocking with Modules + +[Modules](https://vuex.vuejs.org/en/modules.html) are useful for separating out our store into manageable chunks. They also export getters. We can use these in our tests. + +Let’s look at our component: + +``` html + + + +``` +Simple component that includes one action and one getter. + +And the test: + +``` js +import { shallow, createLocalVue } from 'vue-test-utils' +import Vuex from 'vuex' +import Modules from '../../../src/components/Modules' +import module from '../../../src/store/module' + +const localVue = createLocalVue() + +localVue.use(Vuex) + +describe('Modules.vue', () => { + let actions + let state + let store + + beforeEach(() => { + state = { + module: { + clicks: 2 + } + } + + actions = { + moduleActionClick: jest.fn() + } + + store = new Vuex.Store({ + state, + actions, + getters: module.getters + }) + }) + + it('calls store action moduleActionClick when button is clicked', () => { + const wrapper = shallow(Modules, { store, localVue }) + const button = wrapper.find('button') + button.trigger('click') + expect(actions.moduleActionClick).toHaveBeenCalled() + }) + + it('Renders state.inputValue in first p tag', () => { + const wrapper = shallow(Modules, { store, localVue }) + const p = wrapper.find('p') + expect(p.text()).toBe(state.module.clicks.toString()) + }) +}) +``` + +### Resources + +- [Example project for this guide](https://github.com/eddyerburgh/vue-test-utils-vuex-example) +- [localVue](../api/options.md#localvue) +- [createLocalVue](../api/createLocalVue.md) From 0f263272d4d0976f904f3a07e04b857a95b7b37a Mon Sep 17 00:00:00 2001 From: Alex-Sokolov Date: Sat, 14 Oct 2017 13:13:44 +0300 Subject: [PATCH 02/75] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B2=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BD=D1=8B=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=86=D1=8B=20=D1=81=20=D1=81=D0=BE=D0=B4=D0=B5=D1=80=D0=B6?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/README.md | 18 +++++++++--------- docs/ru/SUMMARY.md | 18 +++++++++--------- docs/ru/guides/README.md | 17 +++++++++-------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/docs/ru/README.md b/docs/ru/README.md index 2140a591a..2ef07b473 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -1,15 +1,15 @@ # vue-test-utils -`vue-test-utils` is the official unit testing utility library for Vue.js. +`vue-test-utils` — официальная библиотека модульного тестирования для Vue.js. -* [Guides](guides/README.md) - * [Getting Started](guides/getting-started.md) - * [Common Tips](guides/common-tips.md) - * [Choosing a test runner](guides/choosing-a-test-runner.md) - * [Testing SFCs with Jest](guides/testing-SFCs-with-jest.md) - * [Testing SFCs with Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) - * [Using with Vue Router](guides/using-with-vue-router.md) - * [Using with Vuex](guides/using-with-vuex.md) +* [Руководства](guides/README.md) + * [Введение](guides/getting-started.md) + * [Общие советы](guides/common-tips.md) + * [Выбор test-runner'а](guides/choosing-a-test-runner.md) + * [Тестирование однофайловых компонентов с Jest](guides/testing-SFCs-with-jest.md) + * [Тестирование однофайловых компонентов с Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) + * [Использование с Vue Router](guides/using-with-vue-router.md) + * [Использование с Vuex](guides/using-with-vuex.md) * [API](api/README.md) * [createLocalVue](api/createLocalVue.md) * [mount](api/mount.md) diff --git a/docs/ru/SUMMARY.md b/docs/ru/SUMMARY.md index 6d5dafcd5..ea88e0b52 100644 --- a/docs/ru/SUMMARY.md +++ b/docs/ru/SUMMARY.md @@ -1,13 +1,13 @@ -## Table of Contents +## Содержание -* [Guides](guides/README.md) - * [Getting Started](guides/getting-started.md) - * [Common Tips](guides/common-tips.md) - * [Choosing a test runner](guides/choosing-a-test-runner.md) - * [Testing SFCs with Jest](guides/testing-SFCs-with-jest.md) - * [Testing SFCs with Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) - * [Using with Vue Router](guides/using-with-vue-router.md) - * [Using with Vuex](guides/using-with-vuex.md) +* [Руководства](guides/README.md) + * [Введение](guides/getting-started.md) + * [Общие советы](guides/common-tips.md) + * [Выбор test-runner'а](guides/choosing-a-test-runner.md) + * [Тестирование однофайловых компонентов с Jest](guides/testing-SFCs-with-jest.md) + * [Тестирование однофайловых компонентов с Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) + * [Использование с Vue Router](guides/using-with-vue-router.md) + * [Использование с Vuex](guides/using-with-vuex.md) * [API](api/README.md) * [mount](api/mount.md) * [shallow](api/shallow.md) diff --git a/docs/ru/guides/README.md b/docs/ru/guides/README.md index 8e8b6119d..c6d58becd 100644 --- a/docs/ru/guides/README.md +++ b/docs/ru/guides/README.md @@ -1,9 +1,10 @@ -# Guides +# Руководства -* [Getting Started](./getting-started.md) -* [Common Tips](./common-tips.md) -* [Choosing a test runner](./choosing-a-test-runner.md) -* [Using with Jest](./using-with-jest.md) -* [Testing SFCs with Jest](./testing-SFCs-with-jest.md) -* [Testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md) -* [Using with Vuex](./using-with-vuex.md) +* [Введение](./getting-started.md) +* [Общие советы](./common-tips.md) +* [Выбор test-runner'а](./choosing-a-test-runner.md) +* [Использование с Jest](./using-with-jest.md) +* [Тестирование однофайловых компонентов с Jest](./testing-SFCs-with-jest.md) +* [Тестирование однофайловых компонентов с Mocha + webpack](./testing-SFCs-with-mocha-webpack.md) +* [Использование с Vue Router](./using-with-vue-router.md) +* [Использование с Vuex](./using-with-vuex.md) From 5a452ee5ac2c15f24dc01f38c8fe3056d2466a63 Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Wed, 25 Oct 2017 09:14:58 +0300 Subject: [PATCH 03/75] =?UTF-8?q?dom-events.md=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/guides/dom-events.md | 196 +++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 docs/ru/guides/dom-events.md diff --git a/docs/ru/guides/dom-events.md b/docs/ru/guides/dom-events.md new file mode 100644 index 000000000..ba7e493d5 --- /dev/null +++ b/docs/ru/guides/dom-events.md @@ -0,0 +1,196 @@ +# Testing Key, Mouse and other DOM events + +## Trigger events + +The `Wrapper` expose a `trigger` method. It can be used to trigger DOM events. + +```js +const wrapper = mount(MyButton) + +wrapper.trigger('click') +``` + +You should be aware, that find returns a wrapper as well. Assuming `MyComponent` contains a button, the following code clicks the button. + +```js +const wrapper = mount(MyComponent) + +wrapper.find('button').trigger('click') +``` + +## Options + +The trigger method takes an optional `options` object. The properties in the `options` object are added to the Event. + +You can run preventDefault on the event by passing `preventDefault: true` in `options`. + +```js +const wrapper = mount(MyButton) + +wrapper.trigger('click', {preventDefault: true}) +``` + + +## Mouse Click Example + +**Component under test** + +```js + + + +``` + +**Test** + +```js +import YesNoComponent from '@/components/YesNoComponent' +import { mount } from 'vue-test-utils' +import sinon from 'sinon' + +describe('Click event', () => { + it('Click on yes button calls our method with argument "yes"', () => { + const spy = sinon.spy() + const wrapper = mount(YesNoComponent, { + propsData: { + callMe: spy + } + }) + wrapper.find('button.yes').trigger('click') + + spy.should.have.been.calledWith('yes') + }) +}) +``` + +## Keyboard Example + +**Component under test** + +This component allows to increment/decrement the quantity using various keys. + +```js + + + +``` + +**Test** + +```js +import QuantityComponent from '@/components/QuantityComponent' +import { mount } from 'vue-test-utils' + +describe('Key event tests', () => { + it('Quantity is zero by default', () => { + const wrapper = mount(QuantityComponent) + expect(wrapper.vm.quantity).to.equal(0) + }) + + it('Cursor up sets quantity to 1', () => { + const wrapper = mount(QuantityComponent) + wrapper.trigger('keydown.up') + expect(wrapper.vm.quantity).to.equal(1) + }) + + it('Cursor down reduce quantity by 1', () => { + const wrapper = mount(QuantityComponent) + wrapper.vm.quantity = 5 + wrapper.trigger('keydown.down') + expect(wrapper.vm.quantity).to.equal(4) + }) + + it('Escape sets quantity to 0', () => { + const wrapper = mount(QuantityComponent) + wrapper.vm.quantity = 5 + wrapper.trigger('keydown.esc') + expect(wrapper.vm.quantity).to.equal(0) + }) + + it('Magic character "a" sets quantity to 13', () => { + const wrapper = mount(QuantityComponent) + wrapper.trigger('keydown', { + which: 65 + }) + expect(wrapper.vm.quantity).to.equal(13) + }) +}) + +``` + +**Limitations** + +A key name after the dot `keydown.up` is translated to a `keyCode`. This is supported for the following names: + +* enter, tab, delete, esc, space, up, down, left, right + +## Important + +vue-test-utils triggers event synchronously. Consequently, `vue.nextTick` is not required. \ No newline at end of file From f40d6aec4c14f844d118cf0d7e586cd6a6cbc4cf Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Wed, 25 Oct 2017 09:15:10 +0300 Subject: [PATCH 04/75] =?UTF-8?q?README.md=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=20=D0=B2=20=D0=BE=D0=B3=D0=BB=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/README.md | 1 + docs/ru/SUMMARY.md | 1 + docs/ru/guides/README.md | 1 + 3 files changed, 3 insertions(+) diff --git a/docs/ru/README.md b/docs/ru/README.md index 2ef07b473..cf8cf609e 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -5,6 +5,7 @@ * [Руководства](guides/README.md) * [Введение](guides/getting-started.md) * [Общие советы](guides/common-tips.md) + * [Мышь, клавиши и другие события DOM](guides/dom-events.md) * [Выбор test-runner'а](guides/choosing-a-test-runner.md) * [Тестирование однофайловых компонентов с Jest](guides/testing-SFCs-with-jest.md) * [Тестирование однофайловых компонентов с Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) diff --git a/docs/ru/SUMMARY.md b/docs/ru/SUMMARY.md index ea88e0b52..4ceb364de 100644 --- a/docs/ru/SUMMARY.md +++ b/docs/ru/SUMMARY.md @@ -3,6 +3,7 @@ * [Руководства](guides/README.md) * [Введение](guides/getting-started.md) * [Общие советы](guides/common-tips.md) + * [Мышь, клавиши и другие события DOM](guides/dom-events.md) * [Выбор test-runner'а](guides/choosing-a-test-runner.md) * [Тестирование однофайловых компонентов с Jest](guides/testing-SFCs-with-jest.md) * [Тестирование однофайловых компонентов с Mocha + webpack](guides/testing-SFCs-with-mocha-webpack.md) diff --git a/docs/ru/guides/README.md b/docs/ru/guides/README.md index c6d58becd..d6954707d 100644 --- a/docs/ru/guides/README.md +++ b/docs/ru/guides/README.md @@ -2,6 +2,7 @@ * [Введение](./getting-started.md) * [Общие советы](./common-tips.md) +* [Мышь, клавиши и другие события DOM](./dom-events.md) * [Выбор test-runner'а](./choosing-a-test-runner.md) * [Использование с Jest](./using-with-jest.md) * [Тестирование однофайловых компонентов с Jest](./testing-SFCs-with-jest.md) From b89b0600bb051a330967f5a71f83c918f868fa77 Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Wed, 25 Oct 2017 09:16:46 +0300 Subject: [PATCH 05/75] =?UTF-8?q?choosing-a-test-runner.md=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/guides/choosing-a-test-runner.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ru/guides/choosing-a-test-runner.md b/docs/ru/guides/choosing-a-test-runner.md index 692264d5d..8d69377b1 100644 --- a/docs/ru/guides/choosing-a-test-runner.md +++ b/docs/ru/guides/choosing-a-test-runner.md @@ -6,7 +6,7 @@ There are many popular JavaScript test runners, and `vue-test-utils` works with There are a few things to consider when choosing a test runner though: feature set, performance, and support for single-file component (SFC) pre-compilation. After carefully comparing existing libraries, here are two test runners that we recommend: -- [Jest](https://facebook.github.io/jest/docs/en/getting-started.html#content) is the most fully featured test runner. It requires the least configuration, sets up JSDOM by default, provides built-in assertions, and has a great command line user experience. However, you will need a preprocessor to be able to import SFC components in your tests. We have created the `jest-vue` preprocessor which can handle most common SFC features, but it currently does not have 100% feature parity with `vue-loader`. +- [Jest](https://facebook.github.io/jest/docs/en/getting-started.html#content) is the most fully featured test runner. It requires the least configuration, sets up JSDOM by default, provides built-in assertions, and has a great command line user experience. However, you will need a preprocessor to be able to import SFC components in your tests. We have created the `vue-jest` preprocessor which can handle most common SFC features, but it currently does not have 100% feature parity with `vue-loader`. - [mocha-webpack](https://github.com/zinserjan/mocha-webpack) is a wrapper around webpack + Mocha, but with a more streamlined interface and watch mode. The benefits of this setup is that we can get complete SFC support via webpack + `vue-loader`, but it requires more configuration upfront. @@ -29,7 +29,7 @@ require('jsdom-global')() Single-file Vue components (SFCs) require pre-compilation before they can be run in Node or in the browser. There are two recommended ways to perform the compilation: with a Jest preprocessor, or directly use webpack. -The `jest-vue` preprocessor supports basic SFC functionalities, but currently does not handle style blocks or custom blocks, which are only supported in `vue-loader`. If you rely on these features or other webpack-specific configurations, you will need to use a webpack + `vue-loader` based setup. +The `vue-jest` preprocessor supports basic SFC functionalities, but currently does not handle style blocks or custom blocks, which are only supported in `vue-loader`. If you rely on these features or other webpack-specific configurations, you will need to use a webpack + `vue-loader` based setup. Read the following guides for different setups: From 5c9ae5e1538c08131807ea4c8f8bd52af5cc39d5 Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Wed, 25 Oct 2017 09:17:00 +0300 Subject: [PATCH 06/75] =?UTF-8?q?testing-SFCs-with-jest.md=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/guides/testing-SFCs-with-jest.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/ru/guides/testing-SFCs-with-jest.md b/docs/ru/guides/testing-SFCs-with-jest.md index 0bd70718d..8ca1e8f60 100644 --- a/docs/ru/guides/testing-SFCs-with-jest.md +++ b/docs/ru/guides/testing-SFCs-with-jest.md @@ -27,10 +27,10 @@ Next we need to define a unit script in our `package.json`. ## Processing SFCs in Jest -To teach Jest how to process `*.vue` files, we will need to install and configure the `jest-vue` preprocessor: +To teach Jest how to process `*.vue` files, we will need to install and configure the `vue-jest` preprocessor: ``` bash -npm install --save-dev jest-vue +npm install --save-dev vue-jest ``` Next, create a `jest` block in `package.json`: @@ -46,15 +46,15 @@ Next, create a `jest` block in `package.json`: "vue" ], "transform": { - // process *.vue files with jest-vue - ".*\\.(vue)$": "/node_modules/jest-vue" + // process *.vue files with vue-jest + ".*\\.(vue)$": "/node_modules/vue-jest" }, "mapCoverage": true } } ``` -> **Note:** `jest-vue` currently does not support all the features of `vue-loader`, for example custom block support and style loading. In addition, some webpack-specific features such as code-splitting are not supported either. To use them, read the guide on [testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md). +> **Note:** `vue-jest` currently does not support all the features of `vue-loader`, for example custom block support and style loading. In addition, some webpack-specific features such as code-splitting are not supported either. To use them, read the guide on [testing SFCs with Mocha + webpack](./testing-SFCs-with-mocha-webpack.md). ## Handling webpack Aliases From eab2fc2ae70231f4dea287c3e9593bb0c043148d Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Wed, 25 Oct 2017 09:18:18 +0300 Subject: [PATCH 07/75] =?UTF-8?q?setProps.md=20=D0=BD=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/api/wrapper/setProps.md | 40 ++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/ru/api/wrapper/setProps.md b/docs/ru/api/wrapper/setProps.md index 67ff3f3b1..840dcc9dc 100644 --- a/docs/ru/api/wrapper/setProps.md +++ b/docs/ru/api/wrapper/setProps.md @@ -1,13 +1,13 @@ # setProps(props) -Sets `Wrapper` `vm` props and forces update. - -**Note the Wrapper must contain a Vue instance.** - - **Arguments:** - `{Object} props` -- **Example:** +- **Usage:** + +Sets `Wrapper` `vm` props and forces update. + +**Note the Wrapper must contain a Vue instance.** ```js import { mount } from 'vue-test-utils' @@ -16,5 +16,33 @@ import Foo from './Foo.vue' const wrapper = mount(Foo) wrapper.setProps({ foo: 'bar' }) -expect(wrapper.props().foo).toBe('bar') +expect(wrapper.vm.foo).to.equal('bar') ``` + +You can also pass a `propsData` object, which will initialize the Vue instance with passed values. + +``` js +// Foo.vue +export default { + props: { + foo: { + type: String, + required: true + } + } +} +``` + +``` js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +const wrapper = mount(Foo, { + propsData: { + foo: 'bar' + } +}) + +expect(wrapper.vm.foo).to.equal('bar') +``` \ No newline at end of file From df99e9c459d10a4bfc2b20bf596fc2143cbdddbf Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Thu, 26 Oct 2017 14:07:19 +0300 Subject: [PATCH 08/75] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B4=D0=BB=D1=8F=20destroy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/api/wrapper-array/destroy.md | 18 ++++++++++++++++++ docs/ru/api/wrapper/destroy.md | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/ru/api/wrapper-array/destroy.md create mode 100644 docs/ru/api/wrapper/destroy.md diff --git a/docs/ru/api/wrapper-array/destroy.md b/docs/ru/api/wrapper-array/destroy.md new file mode 100644 index 000000000..784eff642 --- /dev/null +++ b/docs/ru/api/wrapper-array/destroy.md @@ -0,0 +1,18 @@ +# destroy() + +Destroys each Vue `Wrapper` in `WrapperArray`. + +- **Example:** + +```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.contains('p')).toBe(true) +divArray.destroy() +expect(divArray.contains('p')).toBe(false) + +``` \ No newline at end of file diff --git a/docs/ru/api/wrapper/destroy.md b/docs/ru/api/wrapper/destroy.md new file mode 100644 index 000000000..b00336a7d --- /dev/null +++ b/docs/ru/api/wrapper/destroy.md @@ -0,0 +1,20 @@ +# destroy() + +Destroys a Vue component instance. + +- **Example:** + +```js +import { mount } from 'vue-test-utils' +import { expect } from 'chai' +import sinon from 'sinon' + +const spy = sinon.stub() +mount({ + render: null, + destroyed () { + spy() + } +}).destroy() +expect(spy.calledOnce).to.equal(true) +``` \ No newline at end of file From 840fddf509390a44ed7a564f449ae3d732936ca5 Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Thu, 26 Oct 2017 14:08:08 +0300 Subject: [PATCH 09/75] =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BA=20=D0=B5=D0=B4=D0=B8=D0=BD=D0=BE?= =?UTF-8?q?=D0=BC=D1=83=20=D0=B2=D0=B8=D0=B4=D1=83=20readme=20&=20summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/README.md | 22 +++++++++++++++++++--- docs/ru/SUMMARY.md | 2 ++ docs/ru/api/README.md | 11 ++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/ru/README.md b/docs/ru/README.md index cf8cf609e..9abd487aa 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -12,13 +12,24 @@ * [Использование с Vue Router](guides/using-with-vue-router.md) * [Использование с Vuex](guides/using-with-vuex.md) * [API](api/README.md) - * [createLocalVue](api/createLocalVue.md) * [mount](api/mount.md) * [shallow](api/shallow.md) * [Mounting Options](api/options.md) + - [context](api/options.md#context) + - [slots](api/options.md#slots) + - [stubs](api/options.md#stubs) + - [mocks](api/options.md#mocks) + - [localVue](api/options.md#localvue) + - [attachToDocument](api/options.md#attachtodocument) + - [attrs](api/options.md#attrs) + - [listeners](api/options.md#listeners) + - [clone](api/options.md#clone) * [Wrapper](api/wrapper/README.md) * [contains](api/wrapper/contains.md) + * [emitted](api/wrapper/emitted.md) + * [emittedByOrder](api/wrapper/emittedByOrder.md) * [find](api/wrapper/find.md) + * [findAll](api/wrapper/findAll.md) * [hasAttribute](api/wrapper/hasAttribute.md) * [hasClass](api/wrapper/hasClass.md) * [hasProp](api/wrapper/hasProp.md) @@ -28,11 +39,13 @@ * [isEmpty](api/wrapper/isEmpty.md) * [isVueInstance](api/wrapper/isVueInstance.md) * [name](api/wrapper/name.md) - * [update](api/wrapper/update.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) + * [destroy](api/wrapper/destroy.md) * [WrapperArray](api/wrapper-array/README.md) * [at](api/wrapper-array/at.md) * [contains](api/wrapper-array/contains.md) @@ -43,8 +56,11 @@ * [is](api/wrapper-array/is.md) * [isEmpty](api/wrapper-array/isEmpty.md) * [isVueInstance](api/wrapper-array/isVueInstance.md) - * [update](api/wrapper-array/update.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) + * [destroy](api/wrapper-array/destroy.md) * [Selectors](api/selectors.md) + * [createLocalVue](api/createLocalVue.md) diff --git a/docs/ru/SUMMARY.md b/docs/ru/SUMMARY.md index 4ceb364de..d0db59c23 100644 --- a/docs/ru/SUMMARY.md +++ b/docs/ru/SUMMARY.md @@ -43,6 +43,7 @@ * [text](api/wrapper/text.md) * [trigger](api/wrapper/trigger.md) * [update](api/wrapper/update.md) + * [destroy](api/wrapper/destroy.md) * [WrapperArray](api/wrapper-array/README.md) * [at](api/wrapper-array/at.md) * [contains](api/wrapper-array/contains.md) @@ -58,5 +59,6 @@ * [setProps](api/wrapper-array/setProps.md) * [trigger](api/wrapper-array/trigger.md) * [update](api/wrapper-array/update.md) + * [destroy](api/wrapper-array/destroy.md) * [Selectors](api/selectors.md) * [createLocalVue](api/createLocalVue.md) diff --git a/docs/ru/api/README.md b/docs/ru/api/README.md index 231254061..b66159f04 100644 --- a/docs/ru/api/README.md +++ b/docs/ru/api/README.md @@ -17,6 +17,7 @@ * [emitted](./wrapper/emitted.md) * [emittedByOrder](./wrapper/emittedByOrder.md) * [find](./wrapper/find.md) + * [findAll](./wrapper/findAll.md) * [hasAttribute](./wrapper/hasAttribute.md) * [hasClass](./wrapper/hasClass.md) * [hasProp](./wrapper/hasProp.md) @@ -26,11 +27,13 @@ * [isEmpty](./wrapper/isEmpty.md) * [isVueInstance](./wrapper/isVueInstance.md) * [name](./wrapper/name.md) - * [update](./wrapper/update.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) + * [destroy](./wrapper/destroy.md) * [WrapperArray](./wrapper-array/README.md) * [at](./wrapper-array/at.md) * [contains](./wrapper-array/contains.md) @@ -41,9 +44,11 @@ * [is](./wrapper-array/is.md) * [isEmpty](./wrapper-array/isEmpty.md) * [isVueInstance](./wrapper-array/isVueInstance.md) - * [update](./wrapper-array/update.md) * [setData](./wrapper-array/setData.md) + * [setMethods](./wrapper-array/setMethods.md) * [setProps](./wrapper-array/setProps.md) * [trigger](./wrapper-array/trigger.md) -* [createLocalVue](./createLocalVue.md) + * [update](./wrapper-array/update.md) + * [destroy](./wrapper-array/destroy.md) * [Selectors](./selectors.md) +* [createLocalVue](./createLocalVue.md) From a8fc9fc438b06e6eaae10457b5e344c76a8a6a64 Mon Sep 17 00:00:00 2001 From: Alex Sokolov Date: Fri, 27 Oct 2017 14:06:26 +0300 Subject: [PATCH 10/75] =?UTF-8?q?dom-events.md=20=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ru/guides/dom-events.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ru/guides/dom-events.md b/docs/ru/guides/dom-events.md index ba7e493d5..d2f4087b9 100644 --- a/docs/ru/guides/dom-events.md +++ b/docs/ru/guides/dom-events.md @@ -27,7 +27,7 @@ You can run preventDefault on the event by passing `preventDefault: true` in `op ```js const wrapper = mount(MyButton) -wrapper.trigger('click', {preventDefault: true}) +wrapper.trigger('click', { preventDefault: true }) ``` @@ -35,7 +35,7 @@ wrapper.trigger('click', {preventDefault: true}) **Component under test** -```js +```html