Manejo de flujos de correo electrónico en las pruebas de Cypress #frontend@twiliosendgrid

Publicado: 2020-11-24

Twilio SendGrid envía muchos correos electrónicos. Para enviar todos nuestros correos electrónicos transaccionales, desde el restablecimiento de la contraseña hasta la verificación del correo electrónico de la cuenta y la exportación de correos electrónicos CSV, utilizamos nuestros propios servicios de backend.

Recientemente superamos un gran hito de más de 3 billones de correos electrónicos enviados.

En nuestros entornos de prueba, enviamos nuestros correos electrónicos a bandejas de entrada de correo electrónico de prueba en servidores Squirrelmail autohospedados para evitar enviar correos electrónicos de prueba a proveedores de servicios de bandeja de entrada de correo electrónico reales, como Gmail. Muchos flujos importantes requieren que el usuario revise su correo electrónico, haga clic en un enlace procesable, redirija de nuevo a la aplicación web y luego continúe en alguna página de descarga o verificación exitosa.

Probamos estas funciones manualmente ingresando nuestras direcciones de correo electrónico de Squirrelmail en los formularios necesarios, haciendo clic en algunos botones y siguiendo los enlaces de correo electrónico para validar que todo funcione como se esperaba. Podemos hacer esto cada vez que se produzcan nuevos cambios en el código para asegurarnos de que no retrocedemos en ninguna parte, pero sería bueno automatizar estos pasos en una prueba de extremo a extremo (E2E) que podemos ejecutar nuevamente cuando queramos. Específicamente, nos gustaría escribir pruebas E2E con Cypress, para no tener que probar estos flujos de correo electrónico potencialmente lentos y confusos manualmente en nuestro propio navegador web cada vez.

Antes de entrar en la publicación, aquí hay un par de artículos que puede interesarle leer primero.

  • Si nunca antes ha escrito pruebas E2E o desea repasar cómo pensar al escribir pruebas E2E, es posible que desee ver esta publicación de blog antes de que comencemos.
  • Si no está familiarizado con el uso de Cypress para escribir pruebas E2E en general, le recomendamos que consulte nuestra descripción general de mil pies sobre la implementación de pruebas de Cypress para sus aplicaciones web; esto le dará una mejor idea de la API de Cypress.

Esta publicación asume que conoce algunas de las funciones de Cypress como cy.task() para ejecutar código arbitrario que definimos en un servidor Node para ayudarnos con el manejo de correos electrónicos. Además, si los fragmentos de código posteriores con TypeScript son un poco confusos, puede aclarar las cosas al ver nuestra publicación de blog sobre cómo escribimos nuestras pruebas de Cypress. Todavía puede modificar el código en sus propias pruebas de Cypress eliminando las definiciones de tipo y manteniendo la sintaxis solo de JavaScript.

No cubriremos cómo configurar su propio servidor de bandeja de entrada de correo electrónico de prueba (como Squirrelmail), pero nos centraremos en automatizar estos pasos relacionados con la búsqueda de correos electrónicos, el análisis de contenido de correo electrónico coincidente y el seguimiento de enlaces de correo electrónico. Esto debería darle una mejor idea de qué tipo de funciones usar e implementar para manejar estos flujos de correo electrónico, suponiendo que tiene un servidor de bandeja de entrada de correo electrónico de prueba y sus propias credenciales para conectarse.

¿Cómo tratamos los flujos de correo electrónico en las pruebas de Cypress?

Para que podamos probar todos los flujos de correo electrónico, creamos complementos cy.task() para:

  • Trate con la conexión y el filtrado a través de las bandejas de entrada de correo electrónico para correos electrónicos con una determinada línea de asunto
  • Recuperar el contenido del cuerpo de un correo electrónico coincidente
  • Eliminar correos electrónicos de la bandeja de entrada de un usuario sin tener que iniciar sesión a través de la interfaz de usuario de Squirrelmail

También tomamos esta ruta porque no poseemos ni tenemos control sobre la interfaz de usuario de Squirrelmail, y no es posible visitar más de un superdominio en una prueba de Cypress ya que las URL para la interfaz de usuario de Squirrelmail viven en un superdominio separado de nuestra aplicación de interfaz implementada. .

Primero instalamos una biblioteca llamada "emailjs-imap-client" para ayudarnos a configurar un cliente IMAP para conectarse a nuestra bandeja de entrada de Squirrelmail a través de algunas credenciales y configuraciones de host. Usando esta biblioteca, encapsulamos todas las cosas relacionadas con Squirrelmail dentro de un módulo llamado squirrelmail.ts que luego importaríamos en nuestros plugins/index.ts para nuestras definiciones de función cy.task() .

Antes de ejecutar pruebas que involucren correos electrónicos, debemos eliminar todos los correos electrónicos con la misma línea de asunto para evitar falsos positivos al hacer referencia accidentalmente a un correo electrónico anterior activado en una prueba anterior. Para manejar este caso de uso, implementamos esta tarea para eliminar todos los correos electrónicos con una línea de asunto coincidente en la bandeja de entrada de un usuario de la siguiente manera.


Durante nuestras pruebas, activamos una acción que llevará a que se envíe un correo electrónico a la dirección de correo electrónico de Squirrelmail del usuario y, a menudo, debemos esperar a que el correo electrónico con una línea de asunto que coincida llegue a la bandeja de entrada del correo electrónico del usuario. Este proceso toma de segundos a minutos, dependiendo de qué tan involucrados estén los procesos de back-end. Necesitamos asegurarnos de sondear hasta que llegue o proporcionar un error de tiempo de espera en la prueba para informarnos si algo no funciona o se retrasa en la parte de envío de correo. Dado que ya eliminamos los correos electrónicos con líneas de asunto coincidentes de antemano, podemos estar seguros de que se activó desde nuestra ejecución de prueba si regresa con éxito.

Así es como desarrollamos la funcionalidad para esperar un correo electrónico con una línea de asunto específica como "Exportación de su actividad de correo electrónico" o "Verificación del remitente" para llegar a la bandeja de entrada del correo electrónico de un usuario.

Hasta aquí:

  • Limpiamos la bandeja de entrada del correo electrónico del usuario
  • La prueba se ejecuta y activa el envío de un correo electrónico a la bandeja de entrada del correo electrónico del usuario.
  • Esperamos con éxito que el correo electrónico llegara a la bandeja de entrada del correo electrónico del usuario

Ahora, necesitamos obtener el contenido del cuerpo de ese correo electrónico específico.

Afortunadamente, podemos devolver el contenido del cuerpo del correo electrónico coincidente como una cadena que luego tendríamos que analizar para que el enlace de acción regrese a la aplicación web que controlamos y poseemos. El complemento de tareas a continuación busca en la bandeja de entrada de un usuario un correo electrónico con una línea de asunto coincidente y devuelve el contenido del cuerpo para que lo usemos más tarde.

Como breve recordatorio, no podíamos simplemente crear objetos de página para las páginas de Squirrelmail, visitar Squirrelmail a través de la interfaz de usuario, filtrar por una línea de asunto coincidente, abrir el correo electrónico, hacer clic en el enlace procesable directamente y estar en nuestro alegre camino de regreso a nuestra aplicación web, porque no podemos visitar varios superdominios en la misma prueba de Cypress. También es más un antipatrón para visitar páginas y aplicaciones que no controla ni posee.

Después de encontrar los contenidos del cuerpo del correo electrónico coincidentes que activamos en la prueba, tenemos que analizar el contenido HTML, encontrar el enlace de acción, activar una solicitud HTTP al enlace y luego seguir la redirección de regreso a nuestra aplicación web.

Para analizar el contenido HTML del correo electrónico y encontrar las partes del enlace de acción, utilizamos otra biblioteca llamada "cheerio", que carga la cadena HTML y nos permite llamar a funciones similares a jQuery para extraer los botones de acción o enlaces que necesitamos. Una vez que analizamos los enlaces, hacemos una solicitud HTTP al enlace con cy.request() , seguimos el enlace de redireccionamiento a la aplicación web que controlamos y poseemos en el superdominio, y procedemos a verificar los estados de éxito en la página que redirigido a.

En su caso, es posible que no necesite activar una solicitud HTTP al enlace y seguir la redirección de la respuesta si su enlace ya apunta al lugar correcto. Si la URL del enlace ya apunta directamente a su aplicación web, nada le impide extraer la ruta del enlace y hacer un cy.visit(linkPath) para redirigir de nuevo a su aplicación. En el caso de los enlaces de Twilio SendGrid, los enlaces pueden verse como "...sendgrid.net?..." si tiene activado el seguimiento de enlaces para sus correos electrónicos o "brandedlink.com" si tiene la marca del enlace activada. Es por eso que necesitaríamos hacer una solicitud HTTP y extraer la ruta de redirección para hacer un cy.visit(redirectPath) porque el "href" inmediato de los enlaces no coincide con nuestra aplicación web.

A continuación se muestra un ejemplo de cómo encontrar el enlace con cheerio, realizar una solicitud HTTP al enlace y seguir la redirección.

Conclusión

Lo guiamos a través de las muchas funciones del complemento cy.task() que implementamos para realizar más acciones de lectura y eliminación con correos electrónicos coincidentes en nuestras bandejas de entrada. Creamos estas funciones para restablecer correctamente el estado de la bandeja de entrada del correo electrónico del usuario antes de activar estos flujos de correo electrónico en las páginas web, esperar a que los correos electrónicos lleguen a la bandeja de entrada y, finalmente, seguir los enlaces de regreso a sus estados de éxito. A continuación, resumimos los pasos clave para sus pruebas de Cypress:

  • Elimina todos los correos electrónicos con una determinada línea de asunto para evitar falsos positivos con cy.task(“teardownMatchingEmails”) .
  • Inicie sesión con un usuario a través de la API y luego realice una serie de pasos a través de la interfaz de usuario para generar ese correo electrónico que se enviará a la bandeja de entrada del correo electrónico del usuario.
  • Sondee la bandeja de entrada del correo electrónico del usuario para recibir el correo electrónico con la línea de asunto correspondiente a través de cy.task(“awaitEmailInSquirrelmailInbox”) .
  • Lea el contenido del cuerpo del correo electrónico con la línea de asunto correspondiente usando cy.task(“squirrelmailSearchBySubject”) .
  • Analice el enlace de acción adecuado con la biblioteca Cheerio pasando la cadena HTML del cuerpo del correo electrónico y buscando elementos con una sintaxis similar a jQuery.
  • Realice una solicitud HTTP en los enlaces de correo electrónico analizados a través cy.request(“link”) y siga la respuesta de redireccionamiento a la aplicación web o visite la ruta si los enlaces ya coinciden con su superdominio con cy.visit(“emailLinkToWebApp”) .
  • Verifique que se produzcan estados de éxito o realice un seguimiento con más pasos de la interfaz de usuario en la página que posee.

Esperamos que esta publicación de blog lo aliente a comenzar a probar a fondo de principio a fin. Solíamos evitar escribir pruebas E2E con flujos de correo electrónico, pero afortunadamente, descubrimos una manera con estas pruebas de Cypress para ahorrarnos mucho tiempo que habríamos gastado en pruebas de regresión manuales de todo. Aprendimos que es mucho más valioso automatizar y probar todo el flujo de la ruta feliz en lugar de partes del flujo, a menos que muchos pasos dependan de servicios de terceros que no posee ni controla, o no es posible restablecer el usuario a un cierto estado de forma fiable.

Si está interesado en más publicaciones de blog relacionadas con lo que aprendimos sobre cómo escribir pruebas de Cypress para nuestras aplicaciones web, consulte los siguientes artículos:

  • Qué considerar al escribir pruebas E2E
  • Descripción general de 1,000 pies de escritura de pruebas de ciprés
  • TypeScript Todas las cosas en sus pruebas de Cypress
  • Ideas para configurar, organizar y consolidar sus pruebas de Cypress
  • Integración de pruebas Cypress con Docker, Buildkite y CICD