#vuecember2020 #frontend #javascript

Vue Testing Library (2/2)

The simple example from Vue Testing Library (1/2) can be used to build a wide range of complex test scenarios. For this we often need additional resources, which we will look at in more detail here.

Jest DOM Custom Matchers

In many cases it can be useful to import the Jest DOM Custom Matchers. Without these matchers we could only check if an element is present or not in the DOM. If we use the matchers, our possibilities are extended, we can test which text content an element has, which CSS classes or which attributes it has.

<label>Choose your number</label>
<input type="number" value="5" data-testid="input-number" />
<button type="submit" disabled>Next step</button>
const label = getByRole('label')
const numberInput = getByTestId('input-number')
const button = getByRole('button', %7Bname: 'Next step'%7D)

expect(label).toHaveTextContent('Choose your number')
expect(numberInput).toHaveValue(5)
expect(button).toHaveAttribute('disabled')

Screen

So far we have used the queries of the testing library from the render function. However, a different option has developed for this as best practice.

The queries provided by the Testing-Library accept a container as the first argument. Since we usually search the entire document.body for an element during testing, the Testing-Library provides an object called screen, which has every query that exists for document.body. This way, we don't have to drag and drop the queries one by one from the render function, but use the screen object with the corresponding query directly.

const confirmButton = screen.getByRole('button', %7Bname: 'Confirm'%7D)
const addressInput = screen.getByTestId('address-input')

User-Event

With the fireEvent provided by the testing library, it became clearer and clearer that it is not possible to display the potential user events on such an abstract level as one would sometimes like. Since the exact testing of user interaction is the declared goal of the Testing-Library, its documentation recommends to use userEvent instead of fireEvent for simulating events in most cases. The library just needs to be installed in the project and then userEvent can be imported into the corresponding test files and used there.

With userEvent you can for example simulate the clicking on a checkbox:

<div>
  <label htmlFor="checkbox">Check</label>
  <input id="checkbox" type="checkbox" />
</div>
userEvent.click(screen.getByText('Check'))

expect(screen.getByLabelText('Check')).toHaveAttribute('checked', true)

Another example is the deletion of text from an <input> or a <textarea>:

<textarea value="Hello, World!" />
userEvent.clear(screen.getByRole('textbox', 'email'))

expect(screen.getByRole('textbox', 'email')).toHaveAttribute('value', '')