Tab-Navigation per JS – nicht nur in automatisierten Unit-Tests

Als ich letztens am Test-Harness einer Angular9-Komponente gearbeitet habe und die Reaktion auf die Tab-Taste automatisiert testen wollte, war ich doch sehr überrascht, dass dies wohl nach wie vor erst in End-2-End-Tests mit Protractor möglich ist, da die Tab-Taste im Unit-Test nicht simuliert wird. Eine Recherche im Netz ergab, dass das wohl nach wie vor als allgemeines Problem angesehen wird und die einzige Bibliothek (jquery-emulatetab) die ich gefunden habe, setzt auf jQuery auf – eine Abhängigkeit, die so gar nicht in den Stack dieses Angular-Projekts hineinpasst. Da habe ich mich gefragt, ob man ein ähnliches Tool nicht ohne größere Abhängigkeiten umsetzen könnte. Nach einer kurzen Evaluations-Phase war klar, dass dies mit wenigen Zeilen Code gelingen könnte und um das Ergebnis vorweg zu greifen, dieses Tool nennt sich nun „emulate-tab“, bedient sich lediglich nativer Browser-Funktionen und ist per npm unter MIT-Lizenz verfügbar.

Die Herausforderungen dabei bestanden zum einen darin, mögliche Tab-Ziele und deren Reihenfolge zu ermitteln. Dabei stützt sich das Tool auf die „tabindex“-Property, die manuell oder vom Browser gesetzt wird. Anschließend werden noch einige Elemente, beispielsweise unsichtbare Eingabefelder aussortiert. Zum anderen müssen alle Events simuliert werden, die der Browser bei einem echten Tastendruck auslösen würde. Angefangen beim „keydown“ über „blur“, „focus“ und „keyup“ bis hin zum selektieren von Inhalten im Zielfeld. Insgesamt stellten sich diese aber als wesentlich unkomplizierter heraus, als im Vorfeld befürchtet. So dass die eigentliche Komplexität im Verifizieren des Verhaltens in unterschiedlichen Testumgebungen bestand.

Die Beispielprojekte in Angular-9 mit Material Komponenten, Typescript und RequireJs und purem HTML mit JavaScript mit entsprechenden jeweils automatisierten Testumgebungen (alle karma/Jasmine) zeigen, dass sich das Tool nicht nur in Angular, sondern auch jeder anderen Testumgebung einsetzen lässt. Im ursprünglichem (wesentlich größeren) Projekt setzte ich auch Jest als Test-Runner ein. Selbst npm ist nicht zwingend erforderlich – das Script lässt sich auch direkt auf der GitHub-Release-Seite herunterladen und so in andere Projekte einbinden.

Nicht nur für Tests – auch bei der Verbesserung der UX auf produktiven Seiten, kann „emulate-tab“ unterstützen. So habe ich beispielsweise einen Fall, in dem ein Button nach dem drücken deaktiviert wird. Das gewollte Verhalten wäre, dass dabei ein beliebiges Feld nach dem Button in den Fokus rückt – das native Verhalten des Browsers selektiert aber das Feld vor dem Button. Da es sich um eine Wiederverwendbare Komponente handelt, ist das Feld nach dem Button nicht bekannt. Durch ein „emulateTab()“ nach dem deaktivieren des Buttons, stellt dies nun keine Herausforderung mehr dar.

Fazit: Das programmatische auslösen einer Tab-Navigation auf Web-Seiten sollte mit „emulate-tab“, einem einfachem kleinen Tool ohne Abhängigkeiten, zukünftig kein größeres Problem mehr darstellen.

Jasmine – so dokumentiert man heute

Was ist Jasmine? Offensichtlich ein Test-Framework für JavaScript-Code. Aber schon in der Einführung zeigt es anschaulich, dass es vor allem auch zur Dokumentation von Software genutzt werden sollte.

Grundsätzlich bin ich, als ein Verfechter von CleanCode, ja der Meinung: Dokumentation von Implementierungsdetails sollte nicht notwendig sein, da der Code selbst so gestaltet werden sollte, dass man keine zusätzlichen Kommentare und Beschreibungen benötigt.

Die Herausforderung zusätzlicher Dokumentation von Softwaredetails (wenn denn mal vorhanden) liegt im Allgemeinen ja darin, diese aktuell und verlässlich zu halten. Sobald ich von der Dokumentation in den Quellcode wechseln muss, um zu prüfen ob die Beschreibung noch aktuell ist, wir diese schnell wertlos. Jasmine ist ein Framework mit dem man sehr schnell seine Dokumentation verfassen kann und zugleich die entsprechenden Testfälle integriert, die beweisen, dass die Software auch genau so arbeitet wie es beschrieben ist. Dazu macht es einem die sprechende API von Jasmine sehr einfach, auch die Umsetzung der Beweise lesbar zu gestalten – ein überzeugendes Beispiel hierzu liefert die eingangs erwähnte Einführung.

Fazit: Neben der Tatsache, dass es Spaß macht ein neues Projekt mit dem schreiben eines Jasmine-Tests zu beginnen, ist die Einführung von Jasmine ein herausragendes Beispiel wie man lesbaren Code gestalten kann.