vue-testing
v0.0.3
Published
Makes Vue Testing And Mocking Become Easier And Much Fun
Downloads
15
Maintainers
Readme
Vue Testing
Let's make Vue Testing And Mocking Become Easier And Much Fun.
Installation
npm install vue-testing inject-loader --save-dev
Motivation
If you're testing without vue-testing
you'll realize that you have a long boilerplate code to mock up your component. Let me show you how it looks. It's taken from https://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html
<!-- example.vue -->
<template>
<div class="msg">{{ msg }}</div>
</template>
<script>
// this dependency needs to be mocked
import SomeService from '../service'
export default {
data () {
return {
msg: SomeService.msg
}
}
}
</script>
// example.spec.js
// Import the component and make the injection preparation
const ExampleInjector = require('!!vue?inject!./example.vue')
// Inject and Mock External Resource
const ExampleWithMocks = ExampleInjector({
// mock it
'../service': {
msg: 'Hello from a mocked service!'
}
})
it('should render', () => {
// Render the component manually
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': ExampleWithMocks
}
}).$mount()
expect(vm.$el.querySelector('.msg').textContent).toBe('Hello from a mocked service!')
})
Magic Vue Properties
Probably, you'll not get frustated with that code. Cause it's simple. until your component uses vue properties that magically injected by some plugin. For example vue-router
injects this.$router
and this.$route
Or vuex
injects this.$store
. It will throw error variable undefined since we not render the whole app. So, How do you handle it without touching your component code? It needs some effort.
<!-- example.vue -->
<template>
<div class="msg">{{ msg }}</div>
</template>
<script>
// this dependency needs to be mocked
import SomeService from '../service'
export default {
data () {
return {
msg: SomeService.msg
}
},
created() {
// Use Magic Properties
if(this.$route.params === someCondition) this.$router.push('/login')
}
}
</script>
// example.spec.js
// Import the component and make the injection preparation
const ExampleInjector = require('!!vue?inject!./example.vue')
// Inject and Mock External Resource
const ExampleWithMocks = ExampleInjector({
// mock it
'../service': {
msg: 'Hello from a mocked service!'
}
})
// You can inject magic properties this way
ExampleWithMocks.beforeCreate = function () {
this.$route = { params: {} }
this.$router = { push: () => {} }
}
it('should render', () => {
// Render the component manually
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': ExampleWithMocks
}
}).$mount()
expect(vm.$el.querySelector('.msg').textContent).toBe('Hello from a mocked service!')
})
Vuex Helper Function
Oke, let's say that you always pass the router params via props since [email protected]
. But you'll still get the problem when you're using vuex helper function like mapActions
, mapStates
, mapGetters
. Sure, you need write more.
<!-- example.vue -->
<template>
<div class="msg">{{ msg }}</div>
</template>
<script>
// this dependency needs to be mocked
import SomeService from '../service'
// Vuex Helper Function
import { mapActions } from 'vuex'
export default {
data () {
return {
msg: SomeService.msg
}
},
methods: {
// Use It!
...mapActions({
test: 'SOME_ACTION'
})
},
created() {
// Use Magic Properties
if(this.$route.params === someCondition) this.$router.push('/login')
// Bind It!
this.test()
}
}
</script>
// example.spec.js
// Import the component and make the injection preparation
const ExampleInjector = require('!!vue?inject!./example.vue')
// Inject and Mock External Resource
const ExampleWithMocks = ExampleInjector({
// mock it
'../service': {
msg: 'Hello from a mocked service!'
},
'vuex': {
mapActions: () => {}
}
})
// Mock The Method To Put Your Spy
ExampleWithMocks.methods = {
...ExampleWithMocks.methods,
test: function() {
return spy
}
}
// You can inject magic properties this way
ExampleWithMocks.beforeCreate = function () {
this.$route = { params: {} }
this.$router = { push: () => {} }
}
it('should render', () => {
// Render the component manually
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': ExampleWithMocks
}
}).$mount()
expect(vm.$el.querySelector('.msg').textContent).toBe('Hello from a mocked service!')
})
Let's Make It Simple!
Let's make it simple with vue-testing
. You'll just need little effort to mock your component constructor. Take a peek.
// example.spec.js
// Import Vue Testing Helpers
import { mockComponent, mount } from 'vue-testing';
// Import the component and make the injection preparation
const ExampleInjector = require('!!vue?inject!./example.vue')
// Mock It!
let Component = mockComponent(ExampleInjector, {
// You can inject component properties via propsData
propsData: {
msg: 'hai'
},
// Even You can inject the local state without breaking your beforeCreate function
// It will save you from mapStates and mapGetters vuex function error in testing
states: {
localState: 'hello',
$route: {
params: {}
},
$router: {
push: () => {}
}
},
// You can inject the actions to be your local methods!
// It will save you from mapActions vuex function error in testing
actions: {
test: () => spy
},
// Default integrated with vuex-saga
// It will save you from mapSagas vuex-saga function error in testing
sagas: {
test: () => {}
},
// Mock the external module
// You can just put all in one scope
'../service': {
msg: 'Hello from a mocked service!'
},
'jquery': () => {}
'external-module': {}
})
describe('ExampleComponent', function () {
let vm;
beforeEach(function () {
// Mount it!
// Mount it in every test scope. So you'll get fresh component
vm = mount(Component)
})
// Focus On Your Test!
it('Some Test', function () {
const actual = vm.$el.querySelector('.msg').textContent
const expected = 'Hello from a mocked service!'
expect(actual).toBe(expected)
})
})
Have You Tested Your Components? You Should Be~
Thank You for Making this useful~
Let's talk about some projects with me
Just Contact Me At:
- Email: [email protected]
- Skype Id: bosnaufal254
- twitter: @BosNaufal
License
MIT Copyright (c) Naufal Rabbani