What is the proper way of testing a component in Vue with API calls?

Viewed 29

I have a problem understand testing Vue components. In the component testing docs, it says:

Component tests should focus on the component's public interfaces rather than internal implementation details. For most components, the public interface is limited to: events emitted, props, and slots. When testing, remember to test what a component does, not how it does it.

Say you have a Form Component:

<template>
  <form @submit.prevent="submitForm">
    Email: <input type="text" data-test="email" v-model="user.email" /> <br />
    First: <input type="text" data-test="first" v-model="user.first" /> <br />
    Last: <input type="text" data-test="last" v-model="user.last" /> <br />
    <button type="submit">Create User</button>
  </form>
</template>

<script>
import { createUser } from '@/api'
import { notify } from '@/helpers'

export default {
  data: () => ({
    user: {
      email: '',
      first: '',
      last: ''
    }
  }),
  methods: {
    async submitForm() {
      try {
        const result = await createUser(this.user)
        notify.success({
          message: 'Success'
        })
        this.$router.push({ name: 'Home' })
      } catch {
        notify.error({
          message: 'Error occurred'
        })
      }
    }
  }
}
</script>

and here's how I test it:

import router from '@/router';
import * as fetchers from '@/api'
import { notify } from '@/helpers'
import fp from 'flush-promises'

test('should save car details', async () => {
  const successSpy = jest.spyOn(notify, 'success')
  const createUserSpy = jest.spyOn(fetchers, 'createUser')
  const routerPushSpy = jest.spyOn(router, 'push')

  const wrapper = mount(Form)

  await wrapper.find('[data-test="email"]').setValue('test@email.com');
  await wrapper.find('[data-test="first"]').setValue('John');
  await wrapper.find('[data-test="last"]').setValue('Doe');
  await wrapper.find('button').trigger('click')
  await fp();

  expect(successSpy).toHaveBeenCalledWith({
    message: 'Success',
  })
  expect(createUserSpy).toHaveBeenCalledWith({
    email: 'test@email.com',
    first: 'John',
    last: 'Doe'
  });
  expect(routerPushSpy).toHaveBeenCalledWith({ name: 'Home' });
});

While this test works, I am not sure if this is the correct way of component testing based on Vue docs. Looks like I'm testing internal details in that test?

How should I do it?

0 Answers
Related