#vuecember2020 #frontend #javascript #vuejs

Vue Testing Library (1/2)

For the testing of a current lottery project we were looking for a testing library that focuses on testing close to the expected user behavior. We found the Vue-Testing-Library, which does not test the specific implementation of components, but their functionality. This is to ensure that if we make changes to the implementation, for example, during refactoring, and the functionality remains the same, the tests remain valid.

The more your tests resemble the way your software is used, the more confidence they can give you. (Principle of the DOM-Testing-Library)

The Vue-Testing-Library is based on the DOM-Testing-Library and @vue/test-utils. It complements the DOM-Testing-Library with APIs that allow working with Vue and only adopts those methods from the @vue/test-utils that it considers useful for user-centric testing.

First of all, no complex setup is necessary to use the Library in your own project. First, the package must be installed, and then the required components must be copied into the individual test files. In practice it looks like this:

yarn add @testing-library/vue
import %7B render, fireEvent %7D from '@testing-library/vue'

For each test we need the render function provided by the Vue-Testing-Library. With this function we can render the component to be tested. This function can take up to three parameters, the component, options and a callback function. In a simple example we only need the first parameter, but for more complex tests it is worth using the other two parameters as well. (For example, the Options can be used to add properties, mocks or vue-state-models to the test!)

In addition to the render function, the Vue-Testing-Library offers a variety of queries that we can use in our tests to grab specific elements from the component. These queries can be imported for the complete test file or they can be dragged from the render function for the individual tests via Destructuring Assignment.

With these methods, we can already test if there are certain elements in the rendered component:

expect(getByRole('button'‚ %7B name: 'Confirm'%7D))

expect(getByLabelText('Date of birth')

There are a lot of queries that are worth looking at to see what possibilities they offer. In order to decide in what situation it is best to use which query, the Vue-Testing-Library provides guidance in its documentation: The queries are listed here in order of priority, with regard to how much they can support the Vue-Testing-Library's goal of enabling user-centric testing.

In order to simulate different events during testing, the Vue-Testing-Library offers fireEvent. This allows events such as the click-event on a button or the completion of an input to be executed. (An alternative is the UserEvent, which allows for even more flexibility and a more accurate simulation of user activity)

A first simple example can be found in the library documentation:

<template>
  <div>
   <p>Times clicked: %7B%7B count %7D%7D</p>
   <button @click="increment">increment</button>
  </div>
</template>

<script>
export default %7B
 data: () => (%7B
  count: 0,
 %7D),

 methods: %7B
  increment() %7B
   this.count++
   %7D,
  %7D,
%7D
</script>
import %7B render, fireEvent %7D from '@testing-library/vue'
import Component from './Component.vue'

test('increments value on click', async () => %7B
 const %7B getByText %7D = render(Component)

 getByText('Times clicked: 0')

 const button = getByText('increment')

 await fireEvent.click(button)

 getByText('Times clicked: 1')
%7D)