Skip to content

feat: add RouterLinkStub #366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/en/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [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)
* [Testing SFCs with Karma](guides/testing-SFCs-with-karma.md)
* [Testing Asynchronous Behavior](guides/testing-async-components.md)
* [Using with Vue Router](guides/using-with-vue-router.md)
* [Using with Vuex](guides/using-with-vuex.md)
Expand Down Expand Up @@ -41,7 +42,6 @@
* [isVueInstance](api/wrapper/isVueInstance.md)
* [name](api/wrapper/name.md)
* [props](api/wrapper/props.md)
* [setComputed](api/wrapper/setComputed.md)
* [setData](api/wrapper/setData.md)
* [setMethods](api/wrapper/setMethods.md)
* [setProps](api/wrapper/setProps.md)
Expand All @@ -68,6 +68,7 @@
* [components](api/components/README.md)
* [TransitionStub](api/components/TransitionStub.md)
* [TransitionGroupStub](api/components/TransitionGroupStub.md)
* [RouterLinkStub](api/components/RouterLinkStub.md)
* [Selectors](api/selectors.md)
* [createLocalVue](api/createLocalVue.md)
* [config](api/config.md)
20 changes: 20 additions & 0 deletions docs/en/api/components/RouterLinkStub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# RouterLinkStub

A component to stub the Vue Router `router-link` component.

You can use this component to find a router-link component in the render tree.

- **Usage:**

To set it as a stub in mounting options:

```js
import { mount, RouterLinkStub } from '@vue/test-utils'

const wrapper = mount(Component, {
stubs: {
RouterLink: RouterLinkStub
}
})
expect(wrapper.find(RouterLinkStub).props().to).toBe('/some/path')
```
202 changes: 202 additions & 0 deletions docs/en/guides/testing-SFCs-with-karma.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Testing Single File Components with Karma

> An example project for this setup is available on [GitHub](https://github.com/eddyerburgh/vue-test-utils-karma-example).

Karma is a test runner that launches browsers, runs tests, and reports them back to us. We're going to use the Mocha framework to write the tests. We'll use the chai library for test assertions.

## Setting up 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 the test dependencies:

``` bash
npm install --save-dev @vue/test-utils karma karma-chrome-launcher karma-mocha karma-sourcemap-loader karma-spec-reporter karma-webpack mocha
```

Next we need to define a test script in our `package.json`.

```json
// package.json
{
"scripts": {
"test": "karma start --single-run"
}
}
```

- The `--single-run` flag tells Karma to run the test suite once.

### Karma Configuration

Create a karma.conf.js file in the index of the project:

```js
// karma.conf.js

var webpackConfig = require('./webpack.config.js')

module.exports = function (config) {
config.set({
frameworks: ['mocha'],

files: [
'test/**/*.spec.js'
],

preprocessors: {
'**/*.spec.js': ['webpack', 'sourcemap']
},

webpack: webpackConfig,

reporters: ['spec'],

browsers: ['Chrome']
})
}
```

This file is used to configure Karma.

We need to preprocess our files with webpack. to do that, we add webpack as a preprocessor, and include our webpack config. We can use the webpack config file in the base of the project without changing anything.

In our configuration, we run the tests in Chrome. To add extra browsers, see [the Browsers section in the Karma docs](http://karma-runner.github.io/2.0/config/browsers.html).

### Picking an Assertion Library

[Chai](http://chaijs.com/) is a popular assertion library that is commonly used alongside Mocha. You may also want to check out [Sinon](http://sinonjs.org/) for creating spies and stubs.

We can install the `karma-chai` plugin to use `chai` in our tests.

``` bash
npm install --save-dev karma-chai
```

### Adding a test

Create a file in `src` named `Counter.vue`:

``` html
<template>
<div>
{{ count }}
<button @click="increment">Increment</button>
</div>
</template>

<script>
export default {
data () {
return {
count: 0
}
},

methods: {
increment () {
this.count++
}
}
}
</script>
```

And create a test file named `test/Counter.spec.js` with the following code:

```js
import { expect } from 'chai'
import { shallow } from '@vue/test-utils'
import Counter from '../src/Counter.vue'

describe('Counter.vue', () => {
it('increments count when button is clicked', () => {
const wrapper = shallow(Counter)
wrapper.find('button').trigger('click')
expect(wrapper.find('div').text()).contains('1')
})
})
```

And now we can run the tests:

```
npm run test
```

Woohoo, we got our tests running!

### Coverage

To setup code coverage to Karma, we can use the `karma-coverage` plugin.

By default, `karma-coverage` won't use source maps to map the coverage reports. So we need to use `babel-plugin-istanbul` to make sure the coverage is mapped correctly.

Install `karma-coverage`, `babel-plugin-istanbul`, and `cross-env`:

```
npm install --save-dev karma-coverage cross-env
```

We're going to use `cross-env` to set a `BABEL_ENV` environment variable. This way we can use babel-plugin-istanbul when we're compiling for our tests—we don't want to include `babel-plugin-istnabul` when we compile our production code:

```
npm install --save-dev babel-plugin-istanbul
```

Update your `.babelrc` file to use `babel-plugin-istanbul` when `BABEL_ENV` is set to test:

```json
{
"presets": [
["env", { "modules": false }],
"stage-3"
],
"env": {
"test": {
"plugins": ["istanbul"]
}
}
}
```

Now update the karma.conf.js file to use coverage. Add `coverage` to the reporters array, and add a coverageReporters field:

```js
// karma.conf.js

module.exports = function (config) {
config.set({
// ...

reporters: ['spec', 'coverage'],

coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
})
}
```

And update the `test` script to set the `BABEL_ENV`:

```json
// package.json
{
"scripts": {
"test": "cross-env BABEL_ENV=test karma start --single-run"
}
}
```

### Resources

- [Example project for this setup](https://github.com/eddyerburgh/vue-test-utils-karma-example)
- [Karma](http://karma-runner.github.io/)
- [Mocha](https://mochajs.org/)
- [Chai](http://chaijs.com/)
- [Sinon](http://sinonjs.org/)
2 changes: 1 addition & 1 deletion docs/en/guides/testing-SFCs-with-mocha-webpack.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('Counter.vue', () => {
And now we can run the test:

```
npm run unit
npm run test
```

Woohoo, we got our tests running!
Expand Down
29 changes: 29 additions & 0 deletions src/components/RouterLinkStub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @flow
const toTypes: Array<Function> = [String, Object]
const eventTypes: Array<Function> = [String, Array]

export default {
name: 'RouterLinkStub',
props: {
to: {
type: toTypes,
required: true
},
tag: {
type: String,
default: 'a'
},
exact: Boolean,
append: Boolean,
replace: Boolean,
activeClass: String,
exactActiveClass: String,
event: {
type: eventTypes,
default: 'click'
}
},
render (h: Function) {
return h(this.tag, undefined, this.$slots.default)
}
}
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import mount from './mount'
import createLocalVue from './create-local-vue'
import TransitionStub from './components/TransitionStub'
import TransitionGroupStub from './components/TransitionGroupStub'
import RouterLinkStub from './components/RouterLinkStub'
import config from './config'

export default {
Expand All @@ -11,5 +12,6 @@ export default {
mount,
shallow,
TransitionStub,
TransitionGroupStub
TransitionGroupStub,
RouterLinkStub
}
52 changes: 52 additions & 0 deletions test/unit/specs/components/RouterLink.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { mount, RouterLinkStub } from '~vue-test-utils'

describe('RouterLinkStub', () => {
it('takes correct props', () => {
const TestComponent = {
template: `
<div>
<router-link
to="to1"
tag="tag1"
exact="exact1"
append="append1"
replace="replace1"
activeClass="activeClass1"
exactActiveClass="exactActiveClass1"
event="event1"
/>
</div>
`
}
const wrapper = mount(TestComponent, {
stubs: {
RouterLink: RouterLinkStub
}
})
const routerLink = wrapper.find(RouterLinkStub)
expect(routerLink.props().to).to.equal('to1')
expect(routerLink.props().tag).to.equal('tag1')
expect(routerLink.props().exact).to.equal('exact1')
expect(routerLink.props().append).to.equal('append1')
expect(routerLink.props().replace).to.equal('replace1')
expect(routerLink.props().activeClass).to.equal('activeClass1')
expect(routerLink.props().exactActiveClass).to.equal('exactActiveClass1')
expect(routerLink.props().event).to.equal('event1')
})

it('renders slot content', () => {
const TestComponent = {
template: `
<div>
<router-link>some text</router-link>
</div>
`
}
const wrapper = mount(TestComponent, {
stubs: {
RouterLink: RouterLinkStub
}
})
expect(wrapper.find(RouterLinkStub).text()).to.equal('some text')
})
})