Lidando com fluxos de e-mail em testes Cypress #frontend@twiliosendgrid

Publicados: 2020-11-24

O Twilio SendGrid envia muitos e-mails. Para enviar todos os nossos e-mails transacionais, desde redefinição de senha até verificação de e-mail da conta e exportação de e-mails CSV, usamos nossos próprios serviços de back-end.

Recentemente, passamos por um grande marco de mais de 3 trilhões de e-mails enviados.

Em nossos ambientes de teste, enviamos nossos e-mails para testar caixas de entrada de e-mail em servidores Squirrelmail auto-hospedados para evitar o envio de e-mails de teste para provedores de serviços de caixa de entrada de e-mail reais, como o Gmail. Muitos fluxos importantes exigem que o usuário verifique seu e-mail, clique em um link acionável, redirecione de volta para o aplicativo da Web e continue em alguma página de sucesso de download ou verificação.

Testamos esses recursos manualmente inserindo nossos endereços de e-mail do Squirrelmail nos formulários necessários, clicando em alguns botões e seguindo os links de e-mail para validar que as coisas funcionem conforme o esperado. Podemos fazer isso sempre em novas alterações de código para garantir que não regredimos em nenhum lugar, mas seria bom automatizar essas etapas em um teste de ponta a ponta (E2E) que podemos executar novamente sempre que quisermos. Especificamente, gostaríamos de escrever testes E2E com Cypress, para que não tenhamos que testar manualmente esses fluxos de e-mail potencialmente lentos e confusos em nosso próprio navegador da Web todas as vezes.

Antes de entrarmos no post, aqui estão alguns artigos que você pode estar interessado em ler primeiro.

  • Se você nunca escreveu testes E2E antes ou gostaria de uma atualização sobre como pensar ao escrever testes E2E, você pode querer ver esta postagem no blog antes de começarmos.
  • Se você não estiver familiarizado com o uso do Cypress para escrever testes E2E em geral, recomendamos que você confira nossa visão geral de mil pés sobre a implementação de testes Cypress para seus aplicativos da Web - isso lhe dará uma ideia melhor da API do Cypress.

Este post pressupõe que você conhece algumas das funções do Cypress, como cy.task() , para executar código arbitrário que definimos em um servidor Node para nos ajudar a lidar com e-mails. Além disso, se os trechos de código posteriores com o TypeScript forem um pouco confusos, pode esclarecer as coisas para ver nossa postagem no blog sobre como digitamos nossos testes Cypress. Você ainda pode modificar o código em seus próprios testes Cypress removendo as definições de tipo e mantendo a sintaxe somente JavaScript.

Não abordaremos como configurar seu próprio servidor de caixa de entrada de e-mail de teste (como o Squirrelmail), mas nos concentraremos em automatizar essas etapas relacionadas à pesquisa de e-mails, análise de conteúdo de e-mail correspondente e seguir links de e-mail. Isso deve fornecer uma visão melhor de que tipo de funções usar e implementar para lidar com esses fluxos de e-mail, supondo que você tenha um servidor de caixa de entrada de e-mail de teste e suas próprias credenciais para se conectar.

Como lidamos com fluxos de e-mail em testes Cypress?

Para testarmos todos os fluxos de e-mail, criamos plugins cy.task() para:

  • Lidar com a conexão e filtragem através de caixas de entrada de e-mail para e-mails com uma determinada linha de assunto
  • Recuperando o conteúdo do corpo de um email correspondente
  • Excluindo e-mails da caixa de entrada de um usuário sem precisar fazer login pela interface do usuário do Squirrelmail

Também seguimos esse caminho porque não possuímos ou temos controle sobre a interface do usuário do Squirrelmail e não é possível visitar mais de um superdomínio em um teste do Cypress, pois as URLs da interface do usuário do Squirrelmail estão em um superdomínio separado do nosso aplicativo front-end implantado .

Primeiro instalamos uma biblioteca chamada “emailjs-imap-client” para nos ajudar a configurar um cliente IMAP para se conectar à nossa caixa de entrada do Squirrelmail por meio de algumas credenciais e configurações de host. Usando esta biblioteca, nós encapsulamos todas as coisas relacionadas ao Squirrelmail dentro de um módulo chamado squirrelmail.ts que mais tarde importaríamos em nossos plugins/index.ts para nossas definições de função cy.task() .

Antes da execução de testes envolvendo e-mails, devemos desmontar todos os e-mails com a mesma linha de assunto para evitar falsos positivos ao se referir acidentalmente a um e-mail mais antigo acionado em um teste anterior. Para lidar com esse caso de uso, implementamos essa tarefa para excluir todos os e-mails com uma linha de assunto correspondente na caixa de entrada de um usuário da seguinte maneira.


Durante nossos testes, acionamos uma ação que fará com que um e-mail seja enviado para o endereço de e-mail Squirrelmail do usuário e geralmente precisamos aguardar o e-mail com uma linha de assunto correspondente chegar na caixa de entrada de e-mail do usuário. Esse processo leva de segundos a minutos, dependendo do envolvimento dos processos de back-end. Precisamos ter certeza de pesquisar até que ele chegue ou fornecer um erro de tempo limite no teste para nos informar se algo não está funcionando ou está atrasado na parte de envio de e-mail. Como já excluímos e-mails com linhas de assunto correspondentes de antemão, podemos ter certeza de que ele foi acionado em nosso teste se ele retornar com sucesso.

Aqui está como desenvolvemos a funcionalidade para aguardar que um e-mail com uma linha de assunto específica, como "Exportação de atividade de seu e-mail" ou "Verificação de remetente", chegue à caixa de entrada de e-mail de um usuário.

Tão longe:

  • Limpamos a caixa de entrada de e-mail do usuário
  • O teste é executado e aciona um e-mail a ser enviado para a caixa de entrada de e-mail do usuário
  • Aguardamos com sucesso o e-mail chegar na caixa de entrada de e-mail do usuário

Agora, precisamos obter o conteúdo do corpo desse e-mail específico.

Felizmente, podemos retornar o conteúdo do corpo do email correspondente como uma string que mais tarde teríamos que analisar para que o link de ação retornasse ao aplicativo Web que controlamos e possuímos. O plug-in de tarefa abaixo pesquisa na caixa de entrada de um usuário um e-mail com uma linha de assunto correspondente e retorna o conteúdo do corpo para usarmos mais tarde.

Como um breve lembrete, não poderíamos simplesmente criar objetos de página para as páginas do Squirrelmail, visitar o Squirrelmail através da interface do usuário, filtrar por uma linha de assunto correspondente, abrir o e-mail, clicar diretamente no link acionável e estar no nosso alegre caminho de volta para nosso aplicativo da web, porque não podemos visitar vários superdomínios no mesmo teste Cypress. Também é mais um antipadrão visitar páginas e aplicativos que você não controla ou possui.

Depois de encontrar o conteúdo do corpo do e-mail correspondente que acionamos no teste, precisamos analisar o conteúdo HTML, encontrar o link de ação, acionar uma solicitação HTTP para o link e seguir o redirecionamento de volta ao nosso aplicativo da web.

Para analisar o conteúdo HTML do email e encontrar as partes do link de ação, utilizamos outra biblioteca chamada “cheerio”, que carrega a string HTML e nos permite chamar funções do tipo jQuery para extrair os botões de ação ou links que precisamos. Depois de analisar os links, fazemos uma solicitação HTTP para o link com cy.request() , seguimos o link de redirecionamento de volta para o aplicativo da Web que controlamos e possuímos em um superdomínio e procedemos com a verificação dos estados de sucesso na página que redirecionado para.

No seu caso, talvez você não precise acionar uma solicitação HTTP para o link e seguir o redirecionamento da resposta se o link já apontar para o local correto. Se o URL do link já aponta diretamente para seu aplicativo da web, nada o impede de extrair o caminho do link e fazer um cy.visit(linkPath) para redirecionar de volta ao seu aplicativo. No caso de links do Twilio SendGrid, os links podem se parecer com “…sendgrid.net?…” se você tiver o rastreamento de links ativado para seus e-mails ou “brandedlink.com” se você tiver a marca do link. É por isso que precisaríamos fazer uma solicitação HTTP e extrair o caminho de redirecionamento para fazer um cy.visit(redirectPath) porque o “href” imediato dos links não corresponde ao nosso aplicativo da web.

Abaixo está um exemplo de como encontrar o link com cheerio, fazer uma solicitação HTTP para o link e seguir o redirecionamento.

Conclusão

Orientamos você pelas muitas funções do plug-in cy.task() que implementamos para fazer mais ações de leitura e exclusão com e-mails correspondentes em nossas caixas de entrada. Criamos essas funções para redefinir corretamente o estado da caixa de entrada de e-mail do usuário antes de acionarmos esses fluxos de e-mail nas páginas da Web, aguardar os e-mails chegarem na caixa de entrada e, finalmente, seguir os links de volta para seus estados de sucesso. Resumimos as principais etapas para seus testes Cypress abaixo:

  • Rasgue todos os e-mails com uma determinada linha de assunto para evitar falsos positivos com cy.task(“teardownMatchingEmails”) .
  • Faça login em um usuário por meio da API e, em seguida, execute um conjunto de etapas por meio da interface do usuário para gerar esse e-mail a ser enviado para a caixa de entrada de e-mail do usuário.
  • Pesquise a caixa de entrada de e-mail do usuário para receber o e-mail com a linha de assunto correspondente por meio de cy.task(“awaitEmailInSquirrelmailInbox”) .
  • Leia o conteúdo do corpo do e-mail com a linha de assunto correspondente usando cy.task(“squirrelmailSearchBySubject”) .
  • Analise o link de ação adequado com a biblioteca cheerio passando a string HTML do corpo do email e pesquisando os elementos com uma sintaxe semelhante ao jQuery.
  • Faça uma solicitação HTTP nos links de e-mail analisados ​​por meio cy.request(“link”) e siga a resposta de redirecionamento de volta ao aplicativo da Web ou visite o caminho se os links já corresponderem ao seu superdomínio com cy.visit(“emailLinkToWebApp”) .
  • Verifique se os estados de sucesso ocorrem ou acompanhe mais etapas da interface do usuário na página que você possui.

Esperamos que esta postagem do blog encoraje você a começar a testar completamente do início ao fim. Costumávamos evitar escrever testes E2E com fluxos de e-mail, mas, felizmente, descobrimos uma maneira com esses testes Cypress para nos poupar muito tempo que teríamos gasto na regressão manual testando tudo. Aprendemos que é muito mais valioso automatizar e testar todo o fluxo de caminho feliz do que partes do fluxo, a menos que muitas etapas dependam de serviços de terceiros que você não possui ou controla ou não seja possível redefinir o usuário para um determinado estado de forma confiável.

Se você estiver interessado em mais postagens de blog relacionadas ao que aprendemos sobre como escrever testes Cypress para nossos aplicativos da Web, confira os seguintes artigos:

  • O que considerar ao escrever testes E2E
  • Visão geral de 1.000 pés para escrever testes de cipreste
  • TypeScript Todas as coisas em seus testes Cypress
  • Ideias para configurar, organizar e consolidar seus testes Cypress
  • Integrando testes Cypress com Docker, Buildkite e CICD