lobo_tuerto's notes
Home
Blog
Notes
About

Vue 3 testing cheat sheet

What are the basic constructs used for testing in Vue?

📅Published29 July 2022
🏷️
frontendtestingvue

Lately I’ve found that colocated tests are better.
In this way is easier to see which components are missing some, or just have a quick glance at the tests of that component right there! — as opposed to slowly open a test folder and crawl a hierarchy of test files.

mount vs shallowMount

mount will render the whole component and all of its child components.
shallowMount will stub all the child component.

I think it’s preferably to use mount and only stub the things that you need.

Stubs

This is how you can stub sub components:

import { mount } from '@vue/test-utils'
import App from './App.vue'

test('mount component', () => {
  expect(App).toBeTruthy()

  const wrapper = mount(App, {
    global: {
      stubs: {
        MiniMap: true
      }
    }
  })

  expect(wrapper.text()).toContain('MiniMap')
  expect(wrapper.html()).toContain('<mini-map-stub')

  expect(wrapper.html()).toMatchSnapshot()
})

If you pass true to the stub definition it’ll render a component like:
<component-name-stub attr-1="algo" other-attr="otro"></component-name-stub>
so you can test against <component-name-stub or </component-name-stub>.

Why not test against <component-name-stub>?
Because if you are passing props or assigning attributes — like classes, etc. — then you won’t have a match.

Another way is to provide your own stub template and test against that:

import { mount } from '@vue/test-utils'
import App from './App.vue'

test('mount component 2', () => {
  expect(App).toBeTruthy()

  const wrapper = mount(App, {
    global: {
      stubs: {
        MiniMap: {
          template: '<div>|THE MINI MAP|</div>'
        }
      }
    }
  })

  expect(wrapper.text()).toContain('MiniMap')
  expect(wrapper.text()).toContain('|THE MINI MAP|')

  expect(wrapper.html()).toMatchSnapshot()
})

Why not test against <div>|THE MINI MAP|</div>?
For the same reasons described above for <component-name-stub>.

Props and inject

This is how you pass props to a component being tested and also how you can provide a value for injection:

import { mount } from '@vue/test-utils'
import MiniMapControls from './MiniMapControls.vue'

test('toggles control pane', () => {
  const wrapper = mount(MiniMapControls, {
    props: {
      addedTexts: [],
      frameHeight: 400,
      frameWidth: 600,
      layers: []
    },
    global: {
      provide: {
        ppi: 96
      }
    }
  })

  // ...
})

Test click actions and their effects

We’ll need async tests for this:

import { mount } from '@vue/test-utils'
import MiniMapControls from './MiniMapControls.vue'

test('toggles control pane', async () => {
  const wrapper = mount(MiniMapControls, {
    props: {
      addedTexts: [],
      frameHeight: 400,
      frameWidth: 600,
      layers: []
    },
    global: {
      provide: {
        ppi: 96
      }
    }
  })

  expect(wrapper.find('.control-pane').exists()).toBe(false)

  const addIconButton = wrapper.get('button[name="Add icon"]')

  await addIconButton.trigger('click')
  expect(wrapper.find('.control-pane').exists()).toBe(true)

  await addIconButton.trigger('click')
  expect(wrapper.find('.control-pane').exists()).toBe(false)
})

References


Got comments or feedback?
Follow me on
v-529da0c