Categories
Vue Testing

Unit Test Vue Apps with Vue Test Utils — Child Components and Reactive Properties

Spread the love

With the Vue Test Utils library, we can write and run unit tests for Vue apps easily.

In this article, we’ll look at how to write unit tests with the Vue Test Utils library.

Emitting Event from Child Component

We can check for events that are emitted in a child component.

To do that, we call mount to mount the parent component with the child component.

Then we can emit the event we want on the child:

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

const ChildComponent = {
  template: `
    <div>
      <p>child</p>
    </div>
  `,
}

const ParentComponent = {
  template: `
    <div>
      <child-component @custom="onCustom" />
      <p id='emitted' v-if="emitted">emitted</p>
    </div>
  `,
  data() {
    return { emitted: false }
  },
  methods: {
    onCustom() {
      this.emitted = true
    }
  },
  components: {
    ChildComponent
  }
}

describe('ParentComponent', () => {
  it('shows emitted when child-component emits custom event', async () => {
    const wrapper = mount(ParentComponent)
    await wrapper.findComponent(ChildComponent).vm.$emit('custom')
    expect(wrapper.find('#emitted').text()).toContain('emitted')
  })
})

To mount the child component of ParentComponent with the ParentComponent , we call the mount method.

The findComponent method has ChildComponent as the argument so that we can use the returned component wrapper to emit the custom event with the $emit method.

Then to check if the ‘emitted’ text is displayed, we call the find method to check if it has the 'emitted' string.

Manipulating Component State

We can manipulate component state with the setData or setProps method.

For example, we can write:

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

const Counter = {
  template: `
    <div>
      <p>{{count}}</p>
    </div>
  `,
  data() {
    return { count: 0 }
  },
}

describe('Counter', () => {
  it('renders 10 for count', async () => {
    const wrapper = mount(Counter)
    await wrapper.setData({ count: 10 })
    expect(wrapper.find('p').text()).toContain(10)
  })
})

to call the setData method with the data we want to set.

The key is the key of a reactive property and the value is its value.

To set props, we can use the setProps method:

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

const Foo = {
  template: `
    <div>
      <p>{{foo}}</p>
    </div>
  `,
  props: ['foo']
}

describe('Foo', () => {
  it('renders bar for foo prop', async () => {
    const wrapper = mount(Foo)
    await wrapper.setProps({ foo: 'bar' })
    expect(wrapper.find('p').text()).toContain('bar')
  })
})

We call the setProps method to set the value of the foo prop to 'bar' .

Then we check that if that is rendered in the last line of the test.

Props can also be set when we mount the component:

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

const Foo = {
  template: `
    <div>
      <p>{{foo}}</p>
    </div>
  `,
  props: ['foo']
}

describe('Foo', () => {
  it('renders bar for foo prop', async () => {
    const wrapper = mount(Foo, {
      propsData: {
        foo: 'bar'
      }
    })
    expect(wrapper.find('p').text()).toContain('bar')
  })
})

The 2nd argument of the mount method takes the propsData property to let us mock the props.

Conclusion

We can mock props and set values of reactive properties in our tests and test them.

Child component events can also be tested from the parent.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *