End-to-end Testing
How-tos & Guides
12 min read

Testing emails using Cypress

Learn how to use Cypress to automate an end-to-end workflow that involves both web and email.

Antonello Zanini
Published March 22, 2023
AI Assistant for Playwright
Code AI-powered test steps with the free ZeroStep JavaScript library
Learn more

More and more web apps have adopted automated emails to interact with users. These emails play a key role in the user journey. Thus, a bug in one of these email workflows can represent a serious problem for the reputation of your web application.

In this tutorial, you will learn how to create a script to test an email workflow using Cypress. Specifically, you will see how to fill out a passwordless form in a Cypress script, wait for the authentication email, extract the authentication URL, and use it to log in to a web application.

What are common automated email scenarios?

Automated emails are common in several scenarios. Let’s see the most important ones:

How to test an email workflow with Cypress

In this step-by-step tutorial, you will learn how to test a passwordless authentication scenario with Cypress. In detail, you will learn how to use Cypress to:

  1. Connect to a temporary email service
  2. Retrieve the temporary email address
  3. Connect to the passwordless service you want to test
  4. Fill out the passwordless form with the temporary email address to trigger the automated email workflow
  5. Retrieving the authentication email sent by the passwordless service
  6. Extract the authentication URL from the email and use it to log in to the passwordless service.

If the Cypress script manages to log in, then the test is passed. Otherwise, there is a bug in the email workflow. Note that this is just an example to learn how to test emails with Cypress. You can easily adapt this email testing logic to other scenarios.

Let’s now see how to test an emails using Cypress!

Prerequisites

To follow this Cypress tutorial, you only need to meet the following prerequisite:

If you do not have Node.js on your machine, follow the link above to download and install the latest LTS version of Node.js.

Setting up a Cypress project

Before starting coding, you need to set up a Cypress project. If you already know how to set up a Cypress project or already have one, skip this section and move on to the next step.

First, launch the following command in your terminal to initialize the project folder:

1
mkdir cypress-email-test

This will create an empty cypress-email-test folder.

Next, switch into the newly created directory:

1
cd cypress-email-test

And run the command below:

1
npm init -y

This will initialize an npm project without going through an interactive shell session. You now have a blank npm project containing only a package.json file.

It is time to install Cypress. As stated in Cypress’s official documentation, install Cypress using the command below:

1
npm install cypress --save-dev

This will take a few minutes. During the installation process, Cypress should log the following messages in the terminal:

1
2
3
4
5
6
7
8
9
Installing Cypress (version: 11.0.1)

✔  Downloaded Cypress
✔  Unzipped Cypress
✔  Finished Installation C:\Users\antoz\AppData\Local\Cypress\Cache\11.0.1

You can now open Cypress by running: node_modules\.bin\cypress open

https://on.cypress.io/installing-cypress

You are now ready to launch Cypress. Follow the wizard to initialize a Cypress project. If you run into problems, take a look at the Setting up a Cypress project section from our Testing drag-and-drop workflows in Cypress tutorial.

From now on, email-test.cy.js will be considered as the Cypress spec file containing the email testing logic.

1. Connecting to the Temporary Email Service

Let’s use Cypress to connect to the Guerrilla Mail temporary email service. If you are not familiar with this, a temporary email service provides you with a short-lived email address you can use to receive emails. Guerrilla Email automatically generates a disposable email address that is available for 1 hour.

What makes Guerrilla Email special compared to other disposable email providers is that the email address is tied to your browser session. This means that if you close the Guerrilla Mail tab and reopen it within an hour in the same browser session, the temporary email address will still be the same. This will come in handy for the limitations imposed by Cypress.

Guerrilla Mail is particularly useful when it comes to testing because it is Cypress-friendly. On the other hand, most popular email providers such as Gmail will detect and block Cypress.

You can connect to Guerrilla Mail with Cypress as follows:

1
2
3
4
5
6
7
8
// cypress/e2e/email-test.cy.js

describe("email test spec", () => {
  it("should connect to Guerrilla Mail", () => {
    // connecting to the temporary email provider
    cy.visit("https://www.guerrillamail.com/");
  });
});

Note that the Cypress visit() function allows you to connect to a website through its URL.

2. Retrieving the Temporary Email Address

If you inspect the email HTML element in Guerrilla Mail with Chrome DevTools, you will see:

Here, you can note that Guerrilla Mail stores the temporary email address in a #email-widget <span> HTML element. You can extract this data with Cypress as follows:

1
2
3
4
5
6
// retrieving the temporary email address
cy.get("#email-widget")
  .invoke("text")
  .then((email) => {
    // using the email address...
  });

What this snippet does is select the #email-widget HTML element with the Cypress get() function. Then, it uses the invoke() function to get the text contained in the HTML element. Thus, the email variable will contain the temporary email address below:

1
qlzr3f+c18krq8qm33kg@sharklasers.com

3. Connecting to the Passwordless Service

By default, Cypress only allows you to run commands in a single origin. This means that you cannot connect to websites with different domains in a single test. To overcome this limitation, you need to enable the experimentalSessionAndOrigin config. This experimental option enables cross-origin and improves session support.

Note that this config is available starting from Cypress 9.6. If you are using an older version of Cypress, update it with:

1
npm install cypress@latest --save-dev

Now, open the cypress.config.js file in the root folder of your project. This represents the Cypress config file. In the e2e object, set experimentalSessionAndOrigin to true:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// cypress.config.js

const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    experimentalSessionAndOrigin: true,

    // other configs...
  },
});

Relaunch Cypress, and you should now be able to connect to multiple origins in a single test.

Connect to the passwordless service with the origin() function as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// connecting to the temporary email provider
cy.visit("https://www.guerrillamail.com/");

// retrieving the temporary email address
cy.get("#email-widget")
  .invoke("text")
  .then((email) => {
    // setting the passwordless service origin and
    // passing the email address as an argument
    cy.origin("your-service.com", { args: email }, (email) => {
      // connecting to the login page of
      // the passswordless service
      cy.visit("/login");

      // testing https://your-service.com/login ...
    });
  });

The Cypress origin() function allows you to visit multiple domains of different origins in a single test. Note that Cypress runs the callback functions inside origin() in an entirely separate instance. This means that these callbacks do not have access to any variable defined previously. If you need to use any of these variables, you can pass them to origin() callbacks through the args option. Cypress will copy this data and make it available to the functions inside origin().

In other words, if you do not pass email in args, email would be undefined inside the origin() block. This is why the code above specifies it in the arg object.

origin() accepts a domain string as a parameter and does not perform a page change in the test. If you need to visit a new web page, you have to do it manually with visit(). Note that inside origin() you can visit() with relative paths. Also, make sure to replace your-service.com with the domain string of the website you want to test.

4. Fill Out the Passwordless Form

Chances are that the login page of passwordless service includes a form as below:

A passwordless form generally contains an input field and a button. First, you are supposed to type your email in the input field. Then, you should press the button. When you click the button, the email workflow is triggered.

After submitting the form, you will receive an email to the email address you specified in the form. This email will contain a link. By clicking on the link, you will find yourself logged in the passwordless service. This mechanism enables you to log in without a password. That is why it is called passwordless.

Let’s assume the passwordless form consists of the following two HTML elements:

You can fill out such a form in Cypress using the code below:

1
2
3
4
5
6
// typing the email address in the email input
cy.get("#email").type(email);

// clicking the "CONTINUE" button to trigger
// the email workflow
cy.get("#continue").click();

Note that by clicking the “CONTINUE” button you just triggered the email workflow.

5. Retrieving the Authentication Email

Your Cypress test is now on the https://your-service.com/login page. It is time to go back to Guerrilla Mail page. You can achieve this with visit():

1
cy.visit("https://www.guerrillamail.com/");

This command will close https://your-service.com/login and open https://www.guerrillamail.com/. If Guerrilla Mail did not tie the temporary email address to the browser session, you would get a new address. This would be a problem because you could not verify that you actually received the email. And you could not access its content accordingly. This is why it is so important to use Guerrilla Mail with Cypress.

Then, you have to wait for receiving the authentication email. Specifically, your goal is to identify the authentication email from the welcome email sent by Guerrilla Email. If you inspect the <tr> HTML element associated with the authentication email with your browser’s dev tools, you will see the following:

Note that you can select this HTML element with the following CSS selector:

1
#email_list tr:not(#mr_1)

This gives you all <tr> HTML elements inside #email-list that are not #mr_1, which is the welcome email. Since you expect to receive only the authentication email at this temporary email address, this CSS selector should be enough.

Since receiving an email takes time, you have to wait for the #email_list tr:not(#mr_1) HTML element to show up. You can achieve this with the timeout parameter, as follows:

1
2
3
4
5
6
cy.get("#email_list tr:not(#mr_1)", { timeout: 60000 })
  .should("be.visible")
  .click()
  .then(() => {
    // extracting the authentication link...
  });

Waiting for one minute should be enough. Then, click on the <tr> element to access the email content.

6. Extracting the Authentication URL

Your authentication email should look similar to the image below:

The email content is contained in the .email_body HTML element. So, you can retrieve the authentication URL with the following CSS selector:

1
.email_body a;

Note that your authentication email could contain more than one link, use the first() to click on the first link:

1
cy.get(".email_body a").first().click();

If everything went as expected, you should now be logged in to the passwordless service. You can verify this as follows:

1
2
// verifying that you logged in successfully
cy.url().should("contain", "your-service.com/admin");

This verifies that the URL of the page currently shown in Cypress contains the your-service.com/admin string.

Congrats! You just learned how to test an email workflow in Cypress.

Putting it all together

This is what the complete Cypress script looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// cypress/e2e/email-test.cy.js

describe("email test spec", () => {
  it("should log in", () => {
    // connecting to the temporary email provider
    cy.visit("https://www.guerrillamail.com/it");

    // retrieving the temporary email address
    cy.get("#email-widget")
      .invoke("text")
      .then((email) => {
        // setting the passwordless service origin and
        // passing the email address as an argument
        cy.origin("your-service.com", { args: email }, (email) => {
          // connecting to the login page of
          // the passswordless service
          cy.visit("/login");

          // typing the email address in the email input
          cy.get("#identifier-field").type(email);

          // clicking the "CONTINUE" button to trigger
          // the email workflow
          cy.get(".cl-internal-biknk0").click();
        });
      });

    // visiting Guerrilla Mail again
    cy.visit("https://www.guerrillamail.com/");

    // waiting 1 minute for the authentication email element
    // to be present on the page
    cy.get("#email_list tr:not(#mr_1)", { timeout: 60000 })
      .should("be.visible")
      .click()
      .then(() => {
        // clicking the authentication link contained
        // in the body of the email
        cy.get(".email_body a").first().click();

        // verifying that you logged in successfully
        cy.url().should("contain", "your-service.com/admin");
      });
  });
});

Conclusion

In this tutorial, you learned what you need to test automated emails, when you need to use them, and how to test them in Cypress. Automatic emails are a critical aspect of an application’s success. For this reason, you need to be able to test them.

Here, you saw how to test an automated email workflow with Cypress through a simple script. In detail, you learned how to trigger a passwordless email workflow in Cypress, retrieve the authentication URL in the email sent to a temporary email service, and use it to log in to a service.

Thanks for reading! We hope that you found this article helpful. Feel free to reach out to us on Twitter with any questions, comments, or suggestions.

Get started with Reflect today

Create your first test in 2 minutes, no installation or setup required. Accelerate your testing efforts with fast and maintainable test suites without writing a line of code.

Copyright © Reflect Software Inc. All Rights Reserved.