Testing email with Cypress

Learn how to automate email testing with Cypress and Mailosaur

Before you start

If you don’t already have one, create a Mailosaur account.

Make sure you know how to send email to Mailosaur first. Once you have this working, you’re ready to start testing!

Installing Mailosaur

Extend Cypress, by installing Mailosaur’s custom commands package cypress-mailosaur.

Install cypress-mailosaur via npm:

cd your/project/path
npm install cypress-mailosaur --save-dev

Register the commands by appending an import statement to the cypress/support/commands.js file, within your project folder:

echo "import 'cypress-mailosaur'" >> cypress/support/commands.js

Authenticating with Mailosaur

In order to connect to Mailosaur, you need to add your API key to your tests. You access your API key via the account settings screen.

Option 1: Add API key to cypress.json

{  
  "env": {
    "MAILOSAUR_API_KEY": "your-key-here"
  }
}

Option 2: Add API key to a cypress.env.json file

You can create your own cypress.env.json file that Cypress will automatically check. This is useful because if you add cypress.env.json to your .gitignore file, the values in here can be different for each developer machine.

{  
  "MAILOSAUR_API_KEY": "your-key-here"
}

Option 3: Set API key via a system environment variable

To set the environment variable on your machine, it needs to be prefixed with either CYPRESS_ or cypress_.

export CYPRESS_MAILOSAUR_API_KEY=your-key-here

Send and fetch an email

In this example, we’ll navigate to a password reset page, request a new password link (sent via email) and get that email.

touch cypress/integration/password-reset.spec.js

Now edit the file to something like this:

describe('Password reset', () => {
    const serverId = 'SERVER_ID'; // Replace SERVER_ID with an actual Mailosaur Server ID
    const testEmail = `something.${serverId}@mailosaur.io`

    it('Makes a Password Reset request', () => {
        cy.visit('https://github.com/password_reset')
        cy.title().should('equal', 'Forgot your password?')
        cy.get('#email_field').type(testEmail)
    })

    it('Gets a Password Reset email', () => {
        cy.mailosaurGetMessage(serverId, {
            sentTo: testEmail
        }).then(email => {
            expect(email.subject).to.equal('Reset your password');
        })
    })
})

Gotcha! receivedAfter

By default, the mailosaurGetMessage command only looks for emails that were received by Mailosaur within the last hour.

You can override this, by adding the receivedAfter option, like so:

cy.mailosaurGetMessage(serverId, {
    sentTo: testEmail
}, {
   // Find messages received since Jan 1st 2020. This will be slow!
    receivedAfter: new Date('2020-01-01T00:00:00Z')
})

Now that we have our password reset email, we want to navigate to the link within it, just like an end user would:

describe('Password reset', () => {
    const serverId = 'SERVER_ID'; // Replace SERVER_ID with an actual Mailosaur Server ID
    const testEmail = `something.${serverId}@mailosaur.io`
    
    let passwordResetLink;

    it('Makes a Password Reset request', () => {
        cy.visit('https://github.com/password_reset')
        cy.title().should('contain', 'Forgot your password?')
        cy.get('#email_field').type(testEmail)
        cy.get('form').submit()
    })

    it('Gets a Password Reset email', () => {
        cy.mailosaurGetMessage(serverId, {
            sentTo: testEmail
        }).then(email => {
            expect(email.subject).to.contain('reset your password');
            passwordResetLink = email.text.links[0].href;
        })
    })

    it('Follows the link from the email', () => {
        const validPassword = 'delighted cheese jolly cloud'

        cy.visit(passwordResetLink)
        cy.title().should('contain', 'Change your password')
        cy.get('#password').type(validPassword)
        cy.get('#password_confirmation').type(validPassword)
        cy.get('form').submit()
    })
})