Latest Changes in vue-test-utils

Alex Jover Morales

Recently, I’ve updated my book, Testing Vue.js Components with Jest, to reflect the latest versions of vue-test-utils and Jest.

Doing that, I found out some things changed and other cool features were added to vue-test-utils over the last months.

In this article, I’m going to give you a summary of those changes, so you can upgrade your testing code to vue-test-utils v1 without any problem.

Brace yourself!

shallow to shallowMount

Easy peasy. shallow was renamed to shallowMount.

Thus, the API for creating wrappers now includes mount and shallowMount, depending on whether you want to render children components or just perform a shallow rendering:

import { mount, shallowMount } from '@vue/test-utils';

// Renders SomeComponent but not its children
shallowMount(SomeComponent);

// Renders SomeComponents and all its component subtree
mount(SomeComponent);

Newly added classes and attributes

Before, if you wanted to assert on DOM Element attributes, you had the hasProperty, hasStyle or hasClass methods on the wrapper API:

it('A test', () => {
  let cmp = mount(SomeComponent)
  expect(cmp.hasAttribute('alt', 'Hello')).toBe(true)
  expect(cmp.hasClass('message')).toBe(true)
  expect(cmp.hasStyle('padding-top', '10')).toBe(true)
})

The problem of these methods is that they were not flexible. What if want to perform any other check aside from asserting its existence? Or use the Jest’s awesome snapshot testing features? Nope, that wasn’t possible.

That’s why these methods have been replaced by classes and attributes. In that way, the code above could be rewritten as follows:

it('A test', () => {
  let cmp = mount(SomeComponent)
  expect(cmp.attributes().alt).toBe('Hello')
  expect(cmp.classes()).toContain('message')
  expect(cmp.attributes().style).toContain('padding-top: 10px')
})

And since the very latest release, both classes and attributes have an optional argument to return directly the value for a specific key. The last example could be written as:

it('A test', () => {
  let cmp = mount(SomeComponent)
  expect(cmp.attributes('alt')).toBe('Hello')
  expect(cmp.classes('message')).toBe(true)
  expect(cmp.attributes('style')).toContain('padding-top: 10px')
})

Forms and setValue

Previously, to test a form input with a v-model directive, you had to update the data bound to it and trigger an input event (change in case of radios and selects):

inputCmp.element.value = value
inputCmp.trigger('input')

With the addition of the setValue method, now you just need to call it:

inputCmp.setValue(value)

It might not be game changing, but setValue can make the test shorter, more readable and it’s a nice abstraction for not having to remember what event to trigger depending on which kind of input it is.

Events and emitted

Imagine you have a component with a handleClick methods that emits a message-clicked event. Something like:

<template>
  <span @click="handleClick">Click Me!</span>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('message-clicked', 'Howdy cowboy');
    }
  }
}
</script>

In order to test that an event is emitted, you needed to create a Jest stub and listen to its event:

it('triggers a message-clicked event when a handleClick method is called', () => {
  const stub = jest.fn()
  cmp.vm.$on('message-clicked', stub)
  cmp.vm.handleClick()

  expect(stub).toBeCalledWith('Howdy cowboy')
})

Now, the emitted method has been added to the wrapper API, changing the way to assert for events:

it('triggers a message-clicked event when a handleClick method is called', () => {
  cmp.vm.handleClick()
  expect(cmp.emitted()['message-clicked'][0]).toEqual(['Howdy cowboy'])
})

emitted returns an object which keys are the triggered events, and the value of those keys an array of events triggered with their parameters. For the previous example, it’d be:

{
  "message-clicked": [
    ["Howdy cowboy"] // first event triggered
  ]
}

This example might be a bit contrived, but the emitted method becomes very handy when several events are triggered.

Wrapping Up

Aside from the changes mentioned in the article, several features have been added, such as:

  • Better support for slots, scoped slots, functional components and JSX
  • Addition of the parentComponent option to the mount and shallowMount API
  • Lots of bug fixes

And what’s more, the documentation is now much better.

If you’re not on the latest version just yet, now might be a perfect time to upgrade!

Stay cool 🦄

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#