Home / Blog / How to test custom prop validators in Vue.js
How to test custom prop validators in Vue.js

How to test custom prop validators in Vue.js

Rolf Haug
Rolf Haug
Updated: May 15th 2022

In this article, I will show you how you can test props and custom prop validators in a simple and performant way, without spying on the console error.

Testing Vue.js component props

In this tutorial, we're going to use Jest and Vue Test Utils to test a NotificationMessage component. The component has two props:

A message prop, which uses standard prop validation

props: {
  message: {
    required: true,
    type: String
  }
}

And a type prop, which uses custom prop validation. It must be a string, and any of these values: info error success

props: {
  message: { ... },
    type: {
      required: false,
      type: String,
      default: 'info',
      validator: (value) => [
            'info', 
            'error', 
        '  success'
        ].includes(value.toLowerCase())
  }
}

The type dictates the design of our notification message. When rendered, it looks like this:

If we try to mount our component with an invalid type, Vue will warn us and show a warning like this in the console.

How to test custom prop validators in Vue.js

I'll show you three ways of testing your custom prop validators.

  1. Spying on the console error (not recommended)
  2. Using the prop validator through the vue instance (better, not recommended)
  3. Using the prop validator without mounting the component (recommended, best performance)

1. Test custom prop validators using a spy (not recommended)

A common solution to testing custom prop validators is to spy on the console object for the warning output.

// I advise against using this approach

it('does not throw console error when info type', () => {
  const spy = jest.spyOn(console, 'error')

  mount(NotificationMessage, {
    propsData: {
      type: 'info',
      message: 'I like turtles'
    }
  })

  expect(spy).not.toHaveBeenCalledWith(expect.stringContaining('[Vue warn]: Invalid prop: custom validator check failed for prop "type".'))
})

This technically works, but it is a poor, low-quality test. If we remove the validator completely from our component, the test will still pass, because Vue doesn't throw a warning.

There is a much better way to testing your custom prop validators.

2. Test by using the prop validator through the Vue instance (not recommended)

If you think about it, our prop validator is really just a simple function that accepts an argument and returns a boolean.

type: {
  // ...
  validator: (value) => [
        'info', 
        'error', 
        'success'
    ].includes(value.toLowerCase())
}

We can use and invoke the validator method directly in our tests!

We can access all of the Vue component's options through the $options property of the instance. And with Vue Test Utils, we can access the instance through wrapper.vm after it's mounted.

// I advise against using this approach for performance reasons

it('passes with info type', () => {
  const wrapper = mount(NotificationMessage, {
    propsData: {
      message: 'I like turtles!'
    }
  })
  // Extract the validator
  const validator = wrapper.vm.$options.props.type.validator
  // invoke the validator
  expect(validator('info')).toBe(true)
})

This is a much better approach to testing custom prop validators than spying on the console warning.

  • We're testing the code directly in isolation.
  • If we remove the validator from our component, the test will fail.
  • If the warning message changes in a future update, it won't break our tests.

However, there is one thing we can do to significantly improve the performance of this approach.

3. Test by using the prop validator without mounting the component (recommended)

We can significantly improve the performance of our test suite by not mounting the component.

Our components are compiled when we run our tests, which means that we have access to the props object (and the validator) without mounting the component. This means we can write less code and get improved performance, for free.

This is how I would test a Vue.js prop validator without mounting the component:

it('it passes with info type', () => {
  const validator = NotificationMessage.props.type.validator
    expect(validator('info')).toBe(true))
  expect(validator('batman')).toBe(false)
})

Isn't that cool? So to test all of the cases of our validator, I would do the following:

it('it accepts valid type props', function () {
  const validTypes = ['info', 'error', 'success']
  const validator = NotificationMessage.props.type.validator
  validTypes.forEach((valid) => expect(validator(valid)).toBe(true))
  expect(validator('batman')).toBe(false)
})

There you go, a simple, reliable way of testing your custom prop validators in Vue.js!

Testing standard prop validation in Vue.js

We can use the same performant approach to test any component prop.

When we test standard prop validation, it's enough to assert that the prop object is configured correctly. We can use Jest's toMatchObject matcher to make sure a message prop is defined, required, and must be a string.

it('message prop is required and must be a string', function () {
  expect(NotificationMessage.props).toMatchObject({
    message: {
      type: String,
      required: true
    }
  })
})

This is a solid test case. If we remove or alter the prop configuration in the NotificationMessage component, our test will catch it and fail. 👌

Want to learn more about testing Vue.js and JavaScript?

I hope you've learned something and feel inspired to back your custom prop validators with tests. I've prepared a companion repository for this article if you want to play around with the examples.

If you want to learn more about testing in JavaScript and Vue.js applications, I recommend that you check out our testing courses:

We also do in-person training and remote Vue.js workshops, if you want to elevate your entire team or yourself.

Related Courses

Start learning Vue.js for free

Rolf Haug
Rolf Haug
Rolf teaches people about Vue.js and web development through Vue School, talks, and workshops around the world. He co-founded Vue School and is passionate about testing, performance, architecture, and the business aspects of web development.

Comments

Latest Vue School Articles

Why Vue.js is a Great Starting Point for New Coders

Why Vue.js is a Great Starting Point for New Coders

Dive into Vue.js as a beginner with our comprehensive guide. Learn why Vue is perfect for starting your web development journey, with insights into its community, learning resources, and real-world uses.
Eleftheria Batsou
Eleftheria Batsou
The Vue Form Component Pattern: Robust Forms Without the Fuss

The Vue Form Component Pattern: Robust Forms Without the Fuss

Learn to create easy to use Vue forms without a library and take advantage of native HTML validation.
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 200.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.