Testing Vue 3 Apps — Form Triggered Events and Set Values of Form Elements
Tags: vue, programming, webdev, javascript
Published: 2021-01-19 21:30:49

**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.

### Testing Form Triggered Events

We can test the events that are triggered when we submit the form.

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')
})

test('submit event is triggered', async () => {
  const wrapper = mount(EmailInput)
  await wrapper.find('button').trigger('click')
  expect(wrapper.emitted()).toHaveProperty('submit')
})
```

In the 2nd test, we get the button and trigger the `click` event.

Then we check that the `submit` event is emitted with the `wrapper.emitted` method.

We can check what the event triggered with the argument that it’s emitted with.

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('emits the input to its parent', async () => {
  const wrapper = mount(EmailInput)
  await wrapper.find('input').setValue('abc@mail.com')
  await wrapper.find('button').trigger('click')
  expect(wrapper.emitted('submit')[0][0]).toBe('abc@mail.com')
})
```

We mount the `EmailInput` .

Then we call `setValue` on the input to set its value.

Then we trigger the `click` event on the button.

And we check that the `submit` event is emitted with the input value.

### Working with Various Form Elements

We can manipulate other form elements in our tests.

For instance, we can write:

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

const FormComponent = {
  template: `
    <div>
      <form @submit.prevent="submit">
        <input type="email" v-model="form.email">
        <textarea v-model="form.description"/>

        <select v-model="form.city">
          <option value="new-york">New York</option>
          <option value="toronto">Toronto</option>
        </select>

        <input type="checkbox" v-model="form.subscribe"/>
        <input type="radio" value="weekly" v-model="form.interval"/>
        <input type="radio" value="monthly" v-model="form.interval"/>

         <button type="submit">Submit</button>
      </form>
    </div>
  `,
  data() {
    return {
      form: {
        email: '',
        description: '',
        city: '',
        subscribe: false,
        interval: ''
      }
    }
  },
  methods: {
    async submit() {
      this.$emit('submit', this.form)
    }
  }
}

test('submits a form', async () => {
  const wrapper = mount(FormComponent)
  await wrapper.find('input[type=email]').setValue('name@mail.com')
  await wrapper.find('textarea').setValue('Lorem ipsum')
  await wrapper.find('select').setValue('toronto')
  await wrapper.find('input[type=checkbox]').setValue()
  await wrapper.find('input[type=radio][value=monthly]').setValue()
})
```

We can use the `setValue` method with `textarea` , `selecrt` , checkboxes and radio buttons.

Also, we can trigger complex events.

For instance, we can write:

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

const FormComponent = {
  template: `
    <div>
      <form @submit.prevent="submit">
        <input type="email" v-model="form.email">
        <textarea v-model="form.description"/>

        <select v-model="form.city">
          <option value="new-york">New York</option>
          <option value="toronto">Toronto</option>
        </select>

        <input type="checkbox" v-model="form.subscribe"/>
        <input type="radio" value="weekly" v-model="form.interval"/>
        <input type="radio" value="monthly" v-model="form.interval"/>

        <button type="submit">Submit</button>
      </form>
    </div>
  `,
  data() {
    return {
      form: {
        email: '',
        description: '',
        city: '',
        subscribe: false,
        interval: ''
      }
    }
  },
  methods: {
    async submit() {
      this.$emit('submit', this.form)
    }
  }
}

test('submits a form', async () => {
  const wrapper = mount(FormComponent)
  const email = 'name@mail.com'
  const description = 'Lorem ipsum'
  const city = 'toronto'
  await wrapper.find('input[type=email]').setValue(email)
  await wrapper.find('textarea').setValue(description)
  await wrapper.find('select').setValue(city)
  await wrapper.find('input[type=checkbox]').setValue()
  await wrapper.find('input[type=radio][value=monthly]').setValue()
  await wrapper.find('form').trigger('submit.prevent')
  expect(wrapper.emitted('submit')[0][0]).toMatchObject({
    email,
    description,
    city,
    subscribe: true,
    interval: 'monthly',
  })
})
```

We have the same component.

In the test, we mount the component and call `setValue` to set the value of each field.

Then we check if the object we emitted with the `submit` event matches the expected object with the `toMatchObject` method.

We test the `this.form` object in the `submit` method matches what we have in the last line.

### Conclusion

We can test form triggered events and set the values of various form elements in our Vue 3 component tests with Vue Test Utils.