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