#vuecember2020 #frontend #javascript

Vue Testing Library (2/2)

Auf das einfache Beispiel aus Vue Testing Library (1/2) lassen sich vielfältige komplexe Test-Szenarien mit der Vue-Testing-Library aufbauen aufbauen. Dafür benötigen wir oft weitere Mittel, die wir hier genauer betrachten wollen.

Jest DOM Custom Matchers

In vielen Fällen kann es sich lohnen, die Jest DOM Custom Matchers zu importieren. Ohne diese Matcher konnten wir nur überprüfen, ob ein Element im DOM vorkommt bzw. nicht vorkommt. Setzen wir die Matcher ein, erweitern sich unsere Möglichkeiten, wir können testen, welchen Textinhalt ein Element hat, welche CSS-Klassen oder welche Attribute es besitzt.

<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

Bisher haben wir die Queries der Testing-Library aus der render-Funktion gezogen. Dazu hat sich allerdings eine andere Möglichkeit als Best Practice entwickelt.

Die von der Testing-Library zur Verfügung gestellten Queries akzeptieren einen container als erstes Argument. Da wir beim Testen in der Regel den gesamten document.body nach einem Element durchsuchen, stellt die Testing-Library ein Objekt namens screen zur Verfügung, welches jede Query besitzt, die auch für document.body existiert. Auf diese Weise müssen wir nicht mehr die Queries einzeln aus der render-Funktion ziehen, sondern nutzen direkt das screen-Object mit der entsprechenden Query.

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

User-Event

Bei dem von der Testing-Library bereitgestellten fireEvent kristallisierte sich immer mehr hinaus, dass man damit die möglichen User-Events nicht auf so einem abstrakten Level darstellen kann, wie man es manchmal gerne möchte. Da das genaue Testen von User-Interaktion ja das erklärte Ziel der Testing-Library ist, wird in ihrer Dokumentation empfohlen, für Simulieren von Events in den meisten Fällen statt fireEvent userEvent zu benutzen. Die Library muss nur im Projekt installiert werden und dann kann userEvent in die entsprechenden Test-Dateien importiert und dort genutzt werden.

Mit userEvent kann man beispielsweise das Klicken auf eine Checkbox simulieren:

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

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

Ein weiteres Beispiel ist das Löschen von Text aus einem <input> oder einer <textarea>

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

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