Umgang mit E-Mail-Fluss in Cypress-Tests #frontend@twiliosendgrid

Veröffentlicht: 2020-11-24

Twilio SendGrid versendet viele E-Mails. Um alle unsere Transaktions-E-Mails zu senden – von der Passwortzurücksetzung über die Konto-E-Mail-Bestätigung bis hin zum Export von CSV-E-Mails – verwenden wir unsere eigenen Backend-Dienste.

Wir haben kürzlich einen riesigen Meilenstein von über 3 Billionen gesendeten E-Mails überschritten.

In unseren Testumgebungen senden wir unsere E-Mails an Test-E-Mail-Posteingänge auf selbst gehosteten Squirrelmail- Servern, um zu vermeiden, dass Test-E-Mails an tatsächliche E-Mail-Posteingangsdienstanbieter wie Gmail gesendet werden. Bei vielen wichtigen Abläufen muss der Benutzer seine E-Mails abrufen, auf einen umsetzbaren Link klicken, zurück zur Webanwendung umleiten und dann auf einer Download- oder Bestätigungserfolgsseite fortfahren.

Wir testen diese Funktionen manuell, indem wir unsere Squirrelmail-E-Mail-Adressen in die erforderlichen Formulare eingeben, auf einige Schaltflächen klicken und E-Mail-Links folgen, um zu überprüfen, ob alles wie erwartet funktioniert. Wir können dies jedes Mal bei neuen Codeänderungen tun, um sicherzustellen, dass wir nirgendwo zurückgegangen sind, aber es wäre schön, diese Schritte in einem End-to-End (E2E)-Test zu automatisieren, den wir jederzeit wieder ausführen können. Insbesondere möchten wir E2E-Tests mit Cypress schreiben, damit wir diese möglicherweise langsamen und verwirrenden E-Mail-Ströme nicht jedes Mal manuell in unserem eigenen Webbrowser testen müssen.

Bevor wir in die Post kommen, hier sind ein paar Artikel, die Sie vielleicht zuerst lesen möchten.

  • Wenn Sie noch nie E2E-Tests geschrieben haben oder eine Auffrischung darüber wünschen, wie Sie beim Schreiben von E2E-Tests denken sollten, möchten Sie vielleicht diesen Blogbeitrag lesen, bevor wir beginnen.
  • Wenn Sie mit der Verwendung von Cypress zum Schreiben von E2E-Tests im Allgemeinen nicht vertraut sind, empfehlen wir Ihnen dringend, sich unsere 1000-Fuß-Übersicht über die Implementierung von Cypress-Tests für Ihre Webanwendungen anzusehen – dies gibt Ihnen eine bessere Vorstellung von der Cypress-API.

Dieser Beitrag setzt voraus, dass Sie einige der Cypress-Funktionen wie cy.task() kennen, um beliebigen Code auszuführen, den wir in einem Node-Server definieren, um uns beim Umgang mit E-Mails zu unterstützen. Auch wenn die späteren Codeausschnitte mit TypeScript etwas verwirrend sind, kann es die Dinge klären, wenn Sie unseren Blogbeitrag darüber lesen, wie wir unsere Cypress-Tests eingegeben haben. Sie können den Code in Ihren eigenen Cypress-Tests immer noch ändern, indem Sie die Typdefinitionen entfernen und sich an die reine JavaScript-Syntax halten.

Wir werden nicht behandeln, wie Sie Ihren eigenen Test-E-Mail-Posteingangsserver (wie Squirrelmail) einrichten, aber wir konzentrieren uns auf die Automatisierung dieser Schritte im Zusammenhang mit der Suche nach E-Mails, dem Parsen übereinstimmender E-Mail-Inhalte und dem Verfolgen von E-Mail-Links. Dies sollte Ihnen ein besseres Bild davon vermitteln, welche Art von Funktionen Sie verwenden und implementieren müssen, um diese E-Mail-Flüsse zu verarbeiten, vorausgesetzt, Sie haben einen Test-E-Mail-Posteingangsserver und Ihre eigenen Anmeldeinformationen, mit denen Sie sich verbinden können.

Wie gehen wir mit E-Mail-Fluss in Cypress-Tests um?

Damit wir den gesamten E-Mail-Fluss testen können, haben wir cy.task() Plugins entwickelt, um:

  • Umgang mit dem Verbinden und Filtern von E-Mail-Posteingängen nach E-Mails mit einer bestimmten Betreffzeile
  • Abrufen des Textinhalts einer übereinstimmenden E-Mail
  • Löschen von E-Mails aus dem Posteingang eines Benutzers, ohne sich jemals über die Squirrelmail-Benutzeroberfläche anmelden zu müssen

Wir sind diesen Weg auch gegangen, weil wir die Squirrelmail-UI nicht besitzen oder kontrollieren, und es nicht möglich ist, mehr als eine Superdomain in einem Cypress-Test zu besuchen, da die URLs für die Squirrelmail-UI in einer separaten Superdomain von unserer bereitgestellten Frontend-App leben .

Wir haben zuerst eine Bibliothek namens „emailjs-imap-client“ installiert , um uns dabei zu helfen, einen IMAP-Client einzurichten, um über einige Anmeldeinformationen und Hostkonfigurationen eine Verbindung zu unserem Squirrelmail-Posteingang herzustellen. Unter Verwendung dieser Bibliothek haben wir alle Squirrelmail-bezogenen Dinge in einem Modul namens squirrelmail.ts gekapselt, das wir später in unsere plugins/index.ts für unsere cy.task() Funktionsdefinitionen importieren würden.

Bevor Tests mit E-Mails ausgeführt werden, sollten wir alle E-Mails mit derselben Betreffzeile löschen, um Fehlalarme zu vermeiden, die versehentlich auf eine ältere E-Mail verweisen, die in einem früheren Test ausgelöst wurde. Um diesen Anwendungsfall zu handhaben, haben wir diese Aufgabe implementiert, um alle E-Mails mit einer übereinstimmenden Betreffzeile im Posteingang eines Benutzers wie folgt zu löschen.


Während unserer Tests lösen wir eine Aktion aus, die dazu führt, dass eine E-Mail an die Squirrelmail-E-Mail-Adresse des Benutzers gesendet wird, und müssen oft warten, bis die E-Mail mit einer passenden Betreffzeile im E-Mail-Posteingang des Benutzers ankommt. Dieser Vorgang dauert zwischen Sekunden und Minuten, je nachdem, wie involviert die Backend-Prozesse sind. Wir müssen sicherstellen, dass die Abfrage bis zum Eintreffen erfolgt, oder im Test einen Zeitüberschreitungsfehler angeben, um uns mitzuteilen, wenn etwas nicht funktioniert oder sich im Sendeteil der E-Mail verzögert. Da wir bereits zuvor E-Mails mit übereinstimmenden Betreffzeilen gelöscht haben, können wir uns bei erfolgreicher Rückkehr weitgehend sicher sein, dass sie von unserem Testlauf ausgelöst wurde.

So haben wir die Funktion zum Warten auf eine E-Mail mit einer bestimmten Betreffzeile wie „Export Ihrer E-Mail-Aktivität“ oder „Verifizierung des Absenders“ entwickelt, die im E-Mail-Posteingang eines Benutzers ankommt.

Bisher:

  • Wir haben den E-Mail-Posteingang des Benutzers geleert
  • Der Test wird ausgeführt und löst eine E-Mail aus, die an den E-Mail-Posteingang des Benutzers gesendet wird
  • Wir haben erfolgreich darauf gewartet, dass die E-Mail im E-Mail-Posteingang des Benutzers ankommt

Jetzt müssen wir den Textinhalt dieser bestimmten E-Mail abrufen.

Glücklicherweise können wir den Textinhalt der übereinstimmenden E-Mail als Zeichenfolge zurückgeben, die wir später analysieren müssten, damit der Aktionslink zu der Webanwendung zurückkehrt, die wir kontrollieren und besitzen. Das folgende Aufgaben-Plug-in durchsucht den Posteingang eines Benutzers nach einer E-Mail mit einer passenden Betreffzeile und gibt den Textinhalt für uns zur späteren Verwendung zurück.

Zur Erinnerung: Wir konnten nicht einfach Seitenobjekte für die Squirrelmail-Seiten erstellen, Squirrelmail über die Benutzeroberfläche besuchen, nach einer passenden Betreffzeile filtern, die E-Mail öffnen, direkt auf den umsetzbaren Link klicken und uns auf den fröhlichen Weg zurück machen unsere Web-App – da wir nicht mehrere Superdomains im selben Cypress-Test besuchen können. Es ist auch eher ein Antimuster, Seiten und Anwendungen zu besuchen, die Sie nicht kontrollieren oder besitzen.

Nachdem wir den übereinstimmenden E-Mail-Textinhalt gefunden haben, den wir im Test ausgelöst haben, müssen wir den HTML-Inhalt analysieren, den Aktionslink finden, eine HTTP-Anforderung an den Link auslösen und dann der Weiterleitung zurück zu unserer Webanwendung folgen.

Um die E-Mail-HTML-Inhalte zu analysieren und die Aktionslinkteile zu finden, haben wir eine andere Bibliothek namens „cheerio“ verwendet, die den HTML-String lädt und es uns ermöglicht, jQuery-ähnliche Funktionen aufzurufen, um die benötigten Aktionsschaltflächen oder Links zu extrahieren. Sobald wir die Links analysiert haben, stellen wir eine HTTP-Anfrage an den Link mit cy.request() , folgen dem Umleitungslink zurück zu der Web-App, die wir kontrollieren und besitzen, auf der einen Superdomain, und fahren mit der Überprüfung der Erfolgszustände auf der Seite fort, die wir haben umgeleitet zu.

In Ihrem Fall müssen Sie möglicherweise keine HTTP-Anforderung an den Link auslösen und der Weiterleitung der Antwort folgen, wenn Ihr Link bereits auf die richtige Stelle verweist. Wenn die Link-URL bereits direkt auf Ihre Webanwendung verweist, hindert Sie nichts daran, den Linkpfad zu extrahieren und einen cy.visit(linkPath) , um zurück zu Ihrer Anwendung umzuleiten. Im Fall von Twilio SendGrid-Links können die Links wie „…sendgrid.net?…“ aussehen, wenn Sie Link-Tracking für Ihre E-Mails aktiviert haben, oder „brandedlink.com“, wenn Sie Link-Branding aktiviert haben. Aus diesem Grund müssten wir eine HTTP-Anforderung stellen und den Umleitungspfad extrahieren, um einen cy.visit(redirectPath) , da das unmittelbare „href“ der Links nicht mit unserer Web-App übereinstimmt.

Unten ist ein Beispiel dafür, wie Sie den Link mit Cheerio finden, eine HTTP-Anfrage an den Link stellen und der Weiterleitung folgen.

Fazit

Wir haben Sie durch die vielen cy.task() Plugin-Funktionen geführt, die wir implementiert haben, um mehr Lese- und Löschaktionen mit übereinstimmenden E-Mails in unseren Posteingängen durchzuführen. Wir haben diese Funktionen erstellt, um den Status des E-Mail-Posteingangs des Benutzers ordnungsgemäß zurückzusetzen, bevor wir diese E-Mail-Flüsse auf den Webseiten auslösen, warten, bis die E-Mails im Posteingang ankommen, und schließlich den Links zurück zu ihren Erfolgsstatus folgen. Nachfolgend fassen wir die wichtigsten Schritte für Ihre Cypress-Tests zusammen:

  • Zerlegen Sie alle E-Mails mit einer bestimmten Betreffzeile, um Fehlalarme mit cy.task(“teardownMatchingEmails”) zu vermeiden.
  • Melden Sie sich über die API bei einem Benutzer an und führen Sie dann eine Reihe von Schritten über die Benutzeroberfläche durch, um diese E-Mail zu generieren, die an den E-Mail-Posteingang des Benutzers gesendet werden soll.
  • Rufen Sie den E-Mail-Posteingang des Benutzers ab, um die E-Mail mit der passenden Betreffzeile über cy.task(“awaitEmailInSquirrelmailInbox”) zu erhalten.
  • Lesen Sie den Inhalt der E-Mail mit der passenden Betreffzeile mit cy.task(“squirrelmailSearchBySubject”) .
  • Analysieren Sie den richtigen Aktionslink mit der Cheerio-Bibliothek, indem Sie die HTML-Zeichenfolge des E-Mail-Texts übergeben und Elemente mit einer jQuery-ähnlichen Syntax durchsuchen.
  • Stellen Sie eine HTTP-Anfrage an die herausgeparsten E-Mail-Links über cy.request(“link”) und folgen Sie der Umleitungsantwort zurück zur Web-App oder besuchen Sie den Pfad, wenn die Links bereits mit Ihrer Superdomain mit cy.visit(“emailLinkToWebApp”) .
  • Überprüfen Sie, ob Erfolgszustände auftreten, oder führen Sie weitere UI-Schritte auf der Seite durch, deren Inhaber Sie sind.

Wir hoffen, dass dieser Blogbeitrag Sie dazu ermutigt, von Anfang bis Ende gründlich zu testen. Früher haben wir es vermieden, E2E-Tests mit E-Mail-Flows zu schreiben, aber glücklicherweise haben wir mit diesen Cypress-Tests einen Weg gefunden, uns viel Zeit zu sparen, die wir für manuelle Regressionstests aufgewendet hätten. Wir haben gelernt, dass es viel wertvoller ist, den gesamten Happy-Path-Flow zu automatisieren und zu testen als Teile des Flows – es sei denn, viele Schritte beruhen auf Diensten von Drittanbietern, die Sie nicht besitzen oder kontrollieren, oder es ist nicht möglich, den Benutzer auf a zurückzusetzen bestimmten Zustand zuverlässig.

Wenn Sie an weiteren Blogbeiträgen interessiert sind, die sich darauf beziehen, was wir über das Schreiben von Cypress-Tests für unsere Webanwendungen gelernt haben, lesen Sie die folgenden Artikel:

  • Was beim Schreiben von E2E-Tests zu beachten ist
  • 1.000-Fuß-Übersicht über das Schreiben von Cypress-Tests
  • Schreiben Sie alle Dinge in Ihre Cypress-Tests
  • Ideen zum Konfigurieren, Organisieren und Konsolidieren Ihrer Cypress-Tests
  • Integration von Cypress-Tests mit Docker, Buildkite und CICD