Testing Vue 3 Apps — Reactive Properties and Form Handling
Tags: webdev, programming, javascript, vue
Published: 2021-01-19 21:30:18

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

With apps getting more complex than ever, it’s important to test them automatically. We can do this with unit tests, and then we don’t have to test everything by hand.

In this article, we’ll look at how to test Vue 3 apps by writing a simple app and testing it.

### Passing Data to Components

We can pass data to components.

For example, we can write:

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

const Name = {
  template: `
    <div>
      <input v-model="name">
      <div v-if="error">{{ error }}</div>
    </div>
  `,
  props: {
    minLength: {
      type: Number
    }
  },
  computed: {
    error() {
      if (this.name.length < this.minLength) {
        return `Name must be at least ${this.minLength} characters.`
      }
      return
    }
  }
}

test('renders an error if length is too short', () => {
  const wrapper = mount(Name, {
    props: {
      minLength: 10
    },
    data() {
      return {
        name: 'short'
      }
    }
  })
  expect(wrapper.html()).toContain('Name must be at least 10 characters')
})
```

We have the `Name` component with an input field and an error display.

The `error` computed property checks if the `name` is too short and show an error message if it is.

In the test, we pass in the `minLength` prop to the component.

And the `data` method has the `name` reactive property set.

Then we show the error message since the `name` value’s length is shorter than 10.

### Using `setProps`

We can also use the `setProps` method to set the props.

For example, we can write:

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

const Show = {
  template: `
    <div>
      <div v-if="show">{{ greeting }}</div>
    </div>
  `,
  props: {
    show: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      greeting: 'Hello'
    }
  }
}

test('renders a greeting when show is true', async () => {
  const wrapper = mount(Show)
  expect(wrapper.html()).toContain('Hello')
  await wrapper.setProps({ show: false })
  expect(wrapper.html()).not.toContain('Hello')
})
```

We test the `Show` component and check if the `'Hello'` is rendered in the component.

Then we call `setProps` to set the `show` prop to `false` .

Then we check that `'Hello'` isn’t rendered.

### Test Form Handling

We can test form handling by interacting with form elements.

For example, we can write:

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

const EmailInput = {
  template: `
    <div>
      <input type="email" v-model="email">
      <button @click="submit">Submit</button>
    </div>
  `,
  data() {
    return {
      email: ''
    }
  },
  methods: {
    submit() {
      this.$emit('submit', this.email)
    }
  }
}

test('sets the value', async () => {
  const wrapper = mount(EmailInput)
  const input = wrapper.find('input')
  await input.setValue('abc@mail.com')
  expect(input.element.value).toBe('abc@mail.com')
})
```

We have an `EmailInput` component with an input component.

Then we add a test to mount the `EmailInput` component.

Then we get the input with `find` .

And then we call `input.setValue` to set its value.

Then we get the value from the input with `input.element.value` .

### Conclusion

We can pass in the data for the props and test the rendered Vue 3 components with Vue Test Utils.

Also, we can test form inputs with this.