Gestion des flux de messagerie dans les tests Cypress #frontend@twiliosendgrid
Publié: 2020-11-24Twilio SendGrid envoie beaucoup d'e-mails. Pour envoyer tous nos e-mails transactionnels, de la réinitialisation du mot de passe à la vérification de l'e-mail du compte en passant par l'exportation d'e-mails CSV, nous utilisons nos propres services backend.
Nous avons récemment franchi une étape importante avec plus de 3 000 milliards d'e-mails envoyés.
Dans nos environnements de test, nous envoyons nos e-mails à des boîtes de réception de test sur des serveurs Squirrelmail auto-hébergés pour éviter d'envoyer des e-mails de test à des fournisseurs de services de boîte de réception tels que Gmail. De nombreux flux importants exigent que l'utilisateur vérifie son courrier électronique, clique sur un lien exploitable, redirige vers l'application Web, puis continue sur une page de réussite de téléchargement ou de vérification.
Nous testons ces fonctionnalités manuellement en saisissant nos adresses e-mail Squirrelmail dans les formulaires nécessaires, en cliquant sur certains boutons et en suivant les liens e-mail pour valider que tout fonctionne comme prévu. Nous pouvons le faire à chaque fois lors de nouveaux changements de code pour nous assurer que nous n'avons régressé nulle part, mais ce serait bien d'automatiser ces étapes dans un test de bout en bout (E2E) que nous pouvons exécuter à nouveau quand nous le voulons. Plus précisément, nous aimerions écrire des tests E2E avec Cypress, afin que nous n'ayons pas à tester manuellement ces flux de courrier électronique potentiellement lents et déroutants dans notre propre navigateur Web à chaque fois.
Avant d'entrer dans le post, voici quelques articles que vous pourriez être intéressé à lire en premier.
- Si vous n'avez jamais écrit de tests E2E auparavant ou si vous souhaitez un rappel sur la façon de penser lors de l'écriture de tests E2E, vous voudrez peut-être voir ce billet de blog avant de commencer.
- Si vous n'êtes pas familiarisé avec l'utilisation de Cypress pour écrire des tests E2E en général, nous vous recommandons fortement de consulter notre aperçu de mille pieds sur la mise en œuvre de tests Cypress pour vos applications Web. Cela vous donnera une meilleure idée de l'API Cypress.
Cet article suppose que vous connaissez certaines des fonctions Cypress telles que cy.task()
pour exécuter du code arbitraire que nous définissons dans un serveur Node pour nous aider à traiter les e-mails. De plus, si les derniers extraits de code avec TypeScript sont un peu déroutants, cela peut clarifier les choses pour voir notre article de blog sur la façon dont nous avons tapé nos tests Cypress. Vous pouvez toujours modifier le code dans vos propres tests Cypress en supprimant les définitions de type et en vous en tenant à la syntaxe JavaScript uniquement.
Nous n'expliquerons pas comment configurer votre propre serveur de boîte de réception de test (comme Squirrelmail), mais nous nous concentrerons sur l'automatisation de ces étapes liées à la recherche d'e-mails, à l'analyse du contenu des e-mails correspondants et au suivi des liens des e-mails. Cela devrait vous donner une meilleure idée du type de fonctions à utiliser et à implémenter pour gérer ces flux de messagerie, en supposant que vous disposez d'un serveur de boîte de réception de test et de vos propres informations d'identification pour vous connecter.
Comment gérons-nous les flux d'e-mails dans les tests Cypress ?
Pour tester l'intégralité des flux de messagerie, nous avons créé des plugins cy.task()
pour :
- Gérer la connexion et le filtrage des boîtes de réception des e-mails avec une certaine ligne d'objet
- Récupérer le contenu du corps d'un e-mail correspondant
- Suppression des e-mails de la boîte de réception d'un utilisateur sans jamais avoir à se connecter via l'interface utilisateur Squirrelmail
Nous avons également emprunté cette voie car nous ne possédons ni ne contrôlons l'interface utilisateur Squirrelmail, et il n'est pas possible de visiter plus d'un superdomaine dans un test Cypress puisque les URL de l'interface utilisateur Squirrelmail vivent dans un superdomaine distinct de notre application frontale déployée. .
Nous avons d'abord installé une bibliothèque appelée "emailjs-imap-client" pour nous aider à configurer un client IMAP pour se connecter à notre boîte de réception Squirrelmail via certaines informations d'identification et configurations d'hôte. En utilisant cette bibliothèque, nous avons encapsulé toutes les choses liées à Squirrelmail dans un module appelé squirrelmail.ts
que nous allions importer plus tard dans nos plugins/index.ts
pour nos définitions de fonction cy.task()
.
Avant que les tests impliquant des e-mails ne soient exécutés, nous devons supprimer tous les e-mails avec la même ligne d'objet pour éviter les faux positifs en se référant accidentellement à un ancien e-mail déclenché lors d'un test précédent. Pour gérer ce cas d'utilisation, nous avons implémenté cette tâche pour supprimer tous les e-mails avec une ligne d'objet correspondante dans la boîte de réception d'un utilisateur comme suit.
Lors de nos tests, nous déclenchons une action qui entraînera l'envoi d'un e-mail à l'adresse e-mail Squirrelmail de l'utilisateur et nous devons souvent attendre que l'e-mail avec une ligne d'objet correspondante arrive dans la boîte de réception de l'utilisateur. Ce processus prend de quelques secondes à quelques minutes, selon le niveau d'implication des processus backend. Nous devons nous assurer d'interroger jusqu'à ce qu'il arrive ou de fournir une erreur de délai d'attente dans le test pour nous faire savoir si quelque chose ne fonctionne pas ou est retardé dans la partie envoi du courrier. Étant donné que nous avons déjà supprimé les e-mails avec des lignes d'objet correspondantes au préalable, nous pouvons être presque certains qu'il a été déclenché à partir de notre test s'il revient avec succès.
Voici comment nous avons développé la fonctionnalité permettant d'attendre qu'un e-mail avec une ligne d'objet spécifique telle que "Votre exportation d'activité de messagerie" ou "Vérification de l'expéditeur" arrive dans la boîte de réception d'un utilisateur.
Jusque là:

- Nous avons vidé la boîte de réception de l'utilisateur
- Le test s'exécute et déclenche l'envoi d'un e-mail dans la boîte de réception de l'utilisateur
- Nous avons attendu avec succès l'arrivée de l'e-mail dans la boîte de réception de l'utilisateur
Maintenant, nous devons obtenir le contenu du corps de cet e-mail spécifique.
Heureusement, nous pouvons renvoyer le contenu du corps de l'e-mail correspondant sous la forme d'une chaîne que nous devrons analyser ultérieurement pour que le lien d'action revienne à l'application Web que nous contrôlons et possédons. Le plugin de tâche ci-dessous recherche dans la boîte de réception d'un utilisateur un e-mail avec une ligne d'objet correspondante et renvoie le contenu du corps pour que nous l'utilisions plus tard.
Pour rappel, nous ne pouvions pas simplement créer des objets de page pour les pages Squirrelmail, visiter Squirrelmail via l'interface utilisateur, filtrer une ligne d'objet correspondante, ouvrir l'e-mail, cliquer directement sur le lien actionnable et être sur notre joyeux chemin de retour vers notre application Web, car nous ne pouvons pas visiter plusieurs superdomaines dans le même test Cypress. Il s'agit également davantage d'un anti-modèle pour visiter des pages et des applications que vous ne contrôlez pas ou ne possédez pas.
Après avoir trouvé le contenu du corps de l'e-mail correspondant que nous avons déclenché dans le test, nous devons analyser le contenu HTML, trouver le lien d'action, déclencher une requête HTTP vers le lien, puis suivre la redirection vers notre application Web.
Pour analyser le contenu HTML de l'e-mail et trouver les parties du lien d'action, nous avons utilisé une autre bibliothèque appelée "cheerio", qui charge la chaîne HTML et nous permet d'appeler des fonctions de type jQuery pour extraire les boutons d'action ou les liens dont nous avons besoin. Une fois que nous avons analysé les liens, nous faisons une requête HTTP vers le lien avec cy.request()
, suivons le lien de redirection vers l'application Web que nous contrôlons et possédons sur le seul superdomaine, et procédons à la vérification des états de réussite sur la page que nous redirigé vers.
Dans votre cas, vous n'aurez peut-être pas besoin de déclencher une requête HTTP vers le lien et de suivre la redirection de la réponse si votre lien pointe déjà vers le bon endroit. Si l'URL du lien pointe déjà directement vers votre application Web, rien ne vous empêche d'extraire le chemin du lien et de faire un cy.visit(linkPath)
pour rediriger vers votre application. Dans le cas des liens Twilio SendGrid, les liens peuvent ressembler à "… sendgrid.net ?…" si vous avez activé le suivi des liens pour vos e-mails ou "brandedlink.com" si vous avez activé la marque de lien. C'est pourquoi nous aurions besoin de faire une requête HTTP et d'extraire le chemin de redirection pour faire un cy.visit(redirectPath)
car le "href" immédiat des liens ne correspond pas à notre application Web.
Vous trouverez ci-dessous un exemple de recherche du lien avec cheerio, d'envoi d'une requête HTTP au lien et de suivi de la redirection.
Conclusion
Nous vous avons présenté les nombreuses fonctions du plug-in cy.task()
que nous avons implémentées pour effectuer davantage d'actions de lecture et de suppression avec des e-mails correspondants dans nos boîtes de réception. Nous avons créé ces fonctions pour réinitialiser correctement l'état de la boîte de réception des e-mails de l'utilisateur avant de déclencher ces flux d'e-mails dans les pages Web, d'attendre que les e-mails arrivent dans la boîte de réception et enfin de suivre les liens vers leurs états de réussite. Nous résumons ci-dessous les étapes clés de vos tests Cypress :
- Détruisez tous les e-mails avec une certaine ligne d'objet pour éviter les faux positifs avec
cy.task(“teardownMatchingEmails”)
. - Connectez-vous à un utilisateur via l'API, puis suivez une série d'étapes via l'interface utilisateur pour générer cet e-mail à envoyer à la boîte de réception de l'utilisateur.
- Sondez la boîte de réception de l'utilisateur pour recevoir l'e-mail avec la ligne d'objet correspondante via
cy.task(“awaitEmailInSquirrelmailInbox”)
. - Lisez le contenu du corps de l'e-mail avec la ligne d'objet correspondante à l'aide de
cy.task(“squirrelmailSearchBySubject”)
. - Analysez le lien d'action approprié avec la bibliothèque cheerio en transmettant la chaîne HTML du corps de l'e-mail et en recherchant dans les éléments avec une syntaxe de type jQuery.
- Faites une requête HTTP sur les liens de messagerie analysés via
cy.request(“link”)
et suivez la réponse de redirection vers l'application Web ou visitez le chemin si les liens correspondent déjà à votre superdomaine aveccy.visit(“emailLinkToWebApp”)
. - Vérifiez que les états de réussite se produisent ou effectuez un suivi avec d'autres étapes d'interface utilisateur sur la page que vous possédez.
Nous espérons que cet article de blog vous encouragera à commencer à tester minutieusement du début à la fin. Nous avions l'habitude d'éviter d'écrire des tests E2E avec des flux de messagerie, mais heureusement, nous avons trouvé un moyen avec ces tests Cypress de nous faire gagner beaucoup de temps que nous aurions passé à tout tester manuellement. Nous avons appris qu'il est beaucoup plus utile d'automatiser et de tester l'ensemble du flux de chemin heureux plutôt que des parties du flux, à moins que de nombreuses étapes ne reposent sur des services tiers que vous ne possédez ou ne contrôlez pas ou qu'il ne soit pas possible de réinitialiser l'utilisateur à un certain état de manière fiable.
Si vous êtes intéressé par d'autres articles de blog liés à ce que nous avons appris sur l'écriture de tests Cypress pour nos applications Web, consultez les articles suivants :
- Éléments à prendre en compte lors de la rédaction de tests E2E
- Vue d'ensemble de 1 000 pieds des tests d'écriture Cypress
- TypeScript Toutes les choses dans vos tests Cypress
- Idées pour configurer, organiser et consolider vos tests Cypress
- Intégration des tests Cypress avec Docker, Buildkite et CICD