Testing Vue apps
Edd Yerburgh
@eddyerburgh
A web app
Why test?
- Check application works correctly
- Provide documentation
- Easier debugging
- Less bugs
Downsides
E2E
tests
Snapshot tests
Unit tests
E2E Tests
end-to-end tests
browser
.url(devServerURL)
.waitForElementVisible('#app', 5000)
.click('.modal button')
.assert.elementNotPresent('.modal')
.end()
E2E benefits
- Perform realistic user journeys
- Check everything works together
E2E tests are difficult to debug
E2E tests are slow
Unit Tests
E2E
tests
// 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)
})
Unit tests are easy to debug
Unit tests are fast
- Fast
- Easier debugging
Vue SFC
import { mount } from '@vue/test-utils'
import Modal from '../Modal.vue'
test('Modal does not render', {
})
import { mount } from '@vue/test-utils'
import Modal from '../Modal.vue'
test('Modal does not render', {
const wrapper = mount(Modal)
expect(wrapper.isEmpty()).toBe(true)
})
import { mount } from '@vue/test-utils'
import Modal from '../Modal.vue'
test('Modal does not render', {
const wrapper = mount(Modal)
})
import { mount } from '@vue/test-utils'
import Modal from '../Modal.vue'
test('Modal renders correct div', {
const wrapper = mount(Modal)
expect(wrapper.find('div.a-class')
.exists()).toBe(true)
})
import { mount } from '@vue/test-utils'
import Modal from '../Modal.vue'
test('Modal renders correct div', {
const wrapper = mount(Modal)
expect(wrapper.find('div.another-class')
.exists()).toBe(true)
})
??
Component contract
Input
Output
Component
Input
- User action
- Props
- Store
Output
- Rendered output
- Vue events
- Function calls
<modal-component
:visible="displayModal"
:onClose="closeModal"
>
Some content
</modal-component>
test('calls onClose when button is clicked')
test('does not render when not passed visible prop')
test('renders when passed visible prop as true')
test('calls onClose when button is clicked')
test('does not render when not passed visible prop')
test('calls onClose when button is clicked')
<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>
Snapshot tests
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
Compare to previous snapshot
Yes
No
Demo
Snapshot tests safeguard against unintended changes
Snapshot tests are quick to update
E2E
tests
Snapshot tests
Unit tests
Learn more with my book
40% off with code:
ctwvueconfus18
Testing Vue apps
By Edd Yerburgh
Testing Vue apps
What, why, and how of unit testing Vue components
- 2,428