Migration von Enzyme zu RTL
Was ist die React Testing Library?
Die React Testing Library (RTL) ist die empfohlene Testlösung von React. Sie basiert auf dem Konzept des „Black-Box-Tests“ und konzentriert sich auf das Testen von Komponenten auf die gleiche Weise, wie ein Benutzer mit ihnen interagieren würde, und nicht auf die Implementierungsdetails.
Vorteile der Verwendung von RTL
- Tests sind resilient gegenüber Veränderungen. Wenn Sie den Schwerpunkt von Implementierungstests weg verlagern, können Sie Komponenten refaktorieren, ohne dass Tests unterbrochen werden.
- Verlässlichere Tests. RTL testet den gesamten Ablauf und nicht, was sich hinter den Kulissen abspielt, und bleibt so näher an dem, was ein Endbenutzer erleben würde.
- Günstigere Testerstellung. Die RTL-API ist viel kleiner und einfacher als die von Enzyme, sodass es weniger Zeit in Anspruch nimmt, neue Tests zu erstellen und vorhandene zu modifizieren.
- Kostengünstigere Testwartung. Tests müssen nur dann modifiziert werden, wenn sich das Verhalten einer Komponente ändert.
- Enzyme ist auf React-Interna angewiesen, was seine Verwendung auf klassenbasierte Komponenten und nicht auf React-Hooks beschränkt. Bei RTL bestehen diese Beschränkungen nicht.
- Barrierefreiheit ist in das Design von RTL integriert. Durch Abfragen des DOM können Sie leicht feststellen, ob Benutzer, die Hilfsmittel wie Screenreader benötigen, auf Elemente zugreifen können.
Migration zu RTL
RTL ist jetzt die offizielle Testbibliothek von Jutro. Im Laufe der Entwicklung von Jutro wurde klar, dass Enzyme nicht an Veränderungen angepasst werden kann und daher nicht für die Testerfordernisse des Jutro-Teams geeignet ist. Der Hauptunterschied zwischen Enzyme und RTL ist die andere Herangehensweise an das Testen, wobei der Fokus weniger auf der Implementierung und mehr auf dem Output liegt. Aus diesem Grund geben Ihnen mit RTL geschriebene Tests mehr Sicherheit und steigern langfristig Ihre Produktivität.
Es wird empfohlen, dass Ihre RTL-basierten Unit-Tests die abgekündigte userEvent-API aus dem Paket @jutro/legacy nicht verwenden. Sie basiert auf einer älteren Version von @testing-library/user-event und funktioniert in einer modernen Anwendung, z. B. mit React 18, möglicherweise nicht immer wie erwartet. Stattdessen wird empfohlen, die neueste verfügbare Version von @testing-library/user-event (>= 14.4.3) direkt in der Anwendung zu verwenden.
So installieren Sie RTL
Beispieltests in neuen Jutro-Anwendungen werden standardmäßig in RTL geschrieben. Aktualisieren Sie zur Migration älterer Tests Ihre Jutro-Version auf 7.0 oder höher, um die erforderlichen Abh ängigkeiten hinzuzufügen, und schreiben Sie dann Tests manuell mit RTL neu.
Außerdem müssen die Pakete @testing-library/react@14.0.0 und @testing-library/user-event@14.4.3 manuell installiert werden.
Beispiele für gängige Muster in RTL
Im Folgenden finden Sie einige gängige Muster in Enzyme, die in RTL geschrieben wurden. Beachten Sie, dass diese Beispiele keinen vollständigen Code darstellen und möglicherweise nicht in allen Szenarien funktionieren.
Anordnung
Das grundlegende Rendering wird durch das Ersetzen der mount- oder shallow-Funktion durch die render-Funktion erreicht. Sie müssen die render-Funktion aus dem @jutro/test-Paket importieren.
mount(<Component />);
Eine Reihe von Funktionen, die in Enzyme verwendet werden, wurden standardmäßig in die Funktionalität von render gebündelt. Das Beispiel unten zeigt TranslatorProvider, aber ModalNextProvider, ThemeProvider, BreakpointTrackerProvider und router sind ebenfalls enthalten.
mountWithTranslatorContext(<Component />);
Bei der Übergabe von Eigenschaften in einen Kontext müssen Sie ein zweites Argument für render angeben, das Render-Optionen enthält. Die vollständige Liste der Optionen finden Sie hier.
Sie können auch Kontextanbieter mithilfe der Variablen providers konfigurieren, wie im Folgenden dargestellt. Sie können Eigenschaften an den Anbieter übergeben, den Anbieter deaktivieren oder durch Ihren eigenen benutzerdefinierten Anbieter ersetzen. Es gibt fünf Anbieter, die Sie konfigurieren können:
routerglobalizationmodalNextthemebreackpointTracker
mountWithLocaleContext(<Component />, someLocale);
Ausführung
Das Simulieren eines Klick-Ereignisses in RTL ist so einfach wie in Enzyme:
button.simulate('click');
Das Simulieren der Eingabe eines Werts in ein Feld ist in RTL viel einfacher. Die Funktion userEvent.clear löscht das Feld und die Funktion userEvent.type dient zur Eingabe von Zeichen darin. Weitere Informationen zum Dienstprogramm userEvent finden Sie in der userEvent Dokumentation.
input.simulate('change', {
target: {
value: 'myValue',
},
});
In RTL gibt es keine Möglichkeit, ein bestimmtes Element direkt zu fokussieren oder weichzuzeichnen, aber Sie können das Drücken der Tabulatortaste leicht emulieren.
Hinweis: Dies funktioniert nur, wenn die Schaltfläche das erste fokussierbare Element auf der Seite ist. Wenn es das zweite fokussierbare Element ist, wären drei Tabulatortastendrücke erforderlich: zwei, um die Taste zu fokussieren, und ein dritter, um sie zu weichzuzeichnen.
button.simulate('focus');
button.simulate('blur');
Annehmen
So prüfen Sie, ob eine Eingabe den gewünschten Wert hat:
expect(wrapper.find('input')).toHaveProp({
value: 'foo',
});
So prüfen Sie, ob eine Schaltfläche existiert und eine korrekt übersetzte aria-label hat:
const myButton = wrapper.find('Button').at(0);
textWasTranslated(myButton.prop('aria-label'), messageProps.myBtnLabel);
Das folgende Beispiel veranschaulicht, dass Annahmen bei der Verwendung von Mocks identisch sind. Der einzige Unterschied liegt im Aktionscode:
const callbackSpy = jest.fn();
// some actions happen
expect(callbackSpy).toHaveBeenCalledWith(
newValue,
undefined,
expect.anything()
);
Der Matcher className hat in @testing-library/jest-dom einen anderen Namen. Die Liste aller verfügbaren Matcher finden Sie hier.
expect(element).toHaveClassName('someClass');
So prüfen Sie, ob ein Element mit einem bestimmten Text existiert:
expect(wrapper.text()).toEqual('myText');
So prüfen Sie, ob ein Kontrollkästchen aktiviert ist:
const checkbox = wrapper.find('input[id*="test"]');
expect(checkbox.prop('value')).toBe(true);
expect(checkbox.prop('checked')).toBe(true);
Im Folgenden wird gezeigt, wie sie prüfen können, ob die Eingabe barrierefrei deaktiviert ist. Beachten Sie, dass .toBeDisabled() hier nicht verwendet werden kann, da das Vorhandensein oder Nichtvorhandensein des aria-disabled-Attributs dabei nicht berücksichtigt wird.
expect(input.prop('disabled')).toBe(true);