The what, why, and how
@eddyerburgh
// sum.js function sum (a, b) { return a + b } export default sum
// sum.spec.js import sum from './sum' test('returns sum of input', () => { expect(sum(1,3)).toBe(4) })
<template> <div></div> </template> <script> export default { props: ['visible'] } </script>
module.exports = { render: function () { var _vm=this; var _h=_vm.$createElement; var _c=_vm._self._c||_h; return _c('div') } staticRenderFns: [], props: ['visible'] }
Modal.vue
Modal.spec.js
Compiler
Test runner
github.com/eddyerburgh/vue-unit-test-perf-comparison
Test runner | 1000 | 5000 |
---|---|---|
tape | 9.s | 38s |
jest | 22s | 91s |
mocha-webpack | 11s | 38s |
karma-mocha | 33s | 119s |
ava | 625s | 7161s |
vue-test-utils.vuejs.org/en/guides/testing-SFCs-with-jest.html
$ npm install --save-dev jest vue-jest babel-jest
// package.json { // .. "jest": { "transform": { "^.+\\.js$": "babel-jest", "^.+\\.vue$": "vue-jest" }, } // .. }
// package.json { // .. "scripts": { "unit": "jest" } // .. }
$ npm run unit
module.exports = { render: function () { var _vm=this; var _h=_vm.$createElement; var _c=_vm._self._c||_h; return _c('div') } staticRenderFns: [], props: ['visible'] }
$ npm install --save-dev @vue/test-utils
import { mount } from '@vue/test-utils' import Modal from '../Modal.vue'
import { mount } from '@vue/test-utils' import Modal from '../Modal.vue' const wrapper = mount(Modal) wrapper.vm wrapper.element
import { mount } from '@vue/test-utils' import Modal from '../Modal.vue' const wrapper = mount(Modal)
Component
<modal-component :visible="displayModal" :onClose="closeModal" > Some content </modal-component>
test('does not render when not passed visible prop', () => { })
test('does not render when not passed visible prop', () => { const wrapper = mount(Modal) })
test('does not render when not passed visible prop', () => { const wrapper = mount(Modal) expect(wrapper.isEmpty()).toBe(true) })
test('renders when passed visible prop as true', () => { })
test('renders when passed visible prop as true', () => { const wrapper = mount(Modal, { propsData: { visible: true } }) })
test('renders when passed visible prop as true', () => { const wrapper = mount(Modal, { propsData: { visible: true } }) expect(wrapper.isEmpty()).toBe(false) })
test('calls onClose when button is clicked', () => { const onClose = jest.fn() const wrapper = mount(Modal, { propsData: { visible: true, onClose } }) wrapper.find('button').trigger('click') expect(onClose).toHaveBeenCalled() })
test('calls onClose when button is clicked', () => { const onClose = jest.fn() })
test('calls onClose when button is clicked', () => { const onClose = jest.fn() const wrapper = mount(Modal, { propsData: { visible: true, onClose } }) })
test('calls onClose when button is clicked', () => { const onClose = jest.fn() const wrapper = mount(Modal, { propsData: { visible: true, onClose } }) wrapper.find('button').trigger('click') })
test('calls onClose when button is clicked', () => { })
test('renders slot content')
<template> <div v-if="visible"> <button @click="onClose" /> </div> </template> <script> export default { props: ['visible', 'onClose'] } </script>
<template> <div v-if="visible" class="modal is-active"> <div class="modal-background"></div> <div class="modal-content"> <div class="box"> <button @click="onClose" class="delete" aria-label="close"></button> <slot /> </div> </div> </div> </div> </template>
test('renders correctly', () => { const wrapper = mount(Modal, { propsData: { visible: true } }) })
test('renders correctly', () => { })
test('renders correctly', () => { const wrapper = mount(Modal, { propsData: { visible: true } }) expect(wrapper.html()).toMatchSnapshot() })
Does previous
snapshot exist?
create snapshot
compare to previous
snapshot
test passes
No
Yes
does output
match
snapshshot?
create snapshot file
test fails
test passes
Yes
No
// Modal.spec.js.snap exports[`renders correctly 1`] = `"<div class=\\"modal is-active\\"><div class=\\"modal-background\\"></div> <div class=\\"modal-content\\"><div class=\\"box\\"><button aria-label=\\"close\\" class=\\"delete\\"></button> </div></div></div>"`;
// package.json { // .. "jest": { // .. "snapshotSerializers": [ "jest-serializer-vue" ], // .. } // .. }
$ npm install --save-dev jest-serializer-vue
$ npm run unit -- -u
test('renders correctly', () => { })
test('renders correctly', () => { const wrapper = mount(Modal, { slots: { default: '<p>some content</p>' } }) })
test('renders correctly', () => { const wrapper = mount(Modal, { slots: { default: '<p>some content</p>' }, propsData: { visible: true } }) })
test('renders correctly', () => { const wrapper = mount(Modal, { slots: { default: '<p>some content</p>' }, propsData: { visible: true } }) expect(wrapper.html()).toMatchSnapshot() })
vue-test-utils.vuejs.org/