BLOG.siposdani87

Use Gmail account by ImapFlow for mail testing

Integrating Email Account Monitoring with Cypress for End-to-End Testing
By: Dániel Sipos on

End-to-end (E2E) testing is crucial for ensuring the reliability of web applications. Cypress, a popular E2E testing framework, provides a robust environment for writing and running tests. This article explores how to integrate email account monitoring into Cypress tests using the imapflow and mailparser libraries to fetch and parse emails from a Gmail account.

Setting Up the Email Account

First, let’s set up a script to initialize an email account and fetch emails using imapflow and mailparser.

email-account.ts

import * as mailParser from 'mailparser';
import { FetchMessageObject, SequenceString, ImapFlow } from 'imapflow';

export const initInboxEmailAccount = async () => {
    const testAccount = {
        user: 'YOUR_GMAIL_EMAIL_ADDRESS',
        pass: 'YOUR_GMAIL_APP_PASSWORD',
        imap: {
            host: 'imap.gmail.com',
            port: 993,
            secure: true,
        },
    };
    console.log('Testing inbox email account %s', testAccount.user);

    const client = new ImapFlow({
        host: testAccount.imap.host,
        port: testAccount.imap.port,
        secure: testAccount.imap.secure,
        auth: {
            user: testAccount.user,
            pass: testAccount.pass,
        },
    });

    const getInboxMail = async (seq: SequenceString = '*') => {
        console.log('Getting the last email');

        try {
            await client.connect();

            let modifiedSeq = seq;
            // Use negative seq value like ("-1") to get latest 2nd mail
            if (parseInt(seq) <= -1) {
                const status = await client.status('INBOX', { messages: true });
                modifiedSeq = (status.messages + parseInt(seq)).toString();
            }

            let lastMessage: FetchMessageObject | null = null;
            const lock = await client.getMailboxLock('INBOX');

            try {
                lastMessage = await client.fetchOne(modifiedSeq, {
                    source: true,
                });
            } finally {
                lock.release();
            }
            await client.logout();

            if (!lastMessage) {
                console.error('Cannot find any emails');
                return null;
            } else {
                const mail = await mailParser.simpleParser(lastMessage.source);

                return {
                    subject: mail.subject,
                    text: mail.text,
                    html: mail.html,
                };
            }
        } catch (e) {
            console.error(e);
            return null;
        }
    };

    return {
        email: testAccount.user.replace('@', '+1@'),
        getInboxMail,
    };
};

This script does the following:

  1. Initialize Email Account: Sets up the email account configuration for Gmail.
  2. Fetch Emails: Connects to the email server, fetches the latest email, and parses it using mailparser.

Integrating with Cypress

Next, we integrate this email-fetching functionality into Cypress using the cypress.config.ts file.

import { defineConfig } from 'cypress';
import { initInboxEmailAccount } from './cypress/plugins/email-account';
import { SequenceString } from 'imapflow';

export default defineConfig({
    e2e: {
        baseUrl: BASE_URL,
        specPattern: 'cypress/e2e/**/*.spec.{js,jsx,ts,tsx}',
        setupNodeEvents: async (on, config) => {
            const emailAccount = await initInboxEmailAccount();

            on('task', {
                getUserEmail(): string {
                    return emailAccount.email;
                },

                getInboxMail(sec: SequenceString = '*'): Promise<{
                    subject: any;
                    text: any;
                    html: any;
                } | null> {
                    return emailAccount.getInboxMail(sec);
                },
            });

            return config;
        },
    },
    defaultCommandTimeout: 20000,
});

In this configuration:

  1. Setup Node Events: Initializes the email account and sets up tasks to fetch the user email and inbox emails.
  2. Tasks: Defines tasks for getUserEmail and getInboxMail to be used in Cypress tests.

Custom Commands in Cypress

To make use of the email-fetching tasks, we define custom Cypress commands.

Cypress.Commands.add('openInboxMail', (sec: SequenceString = '*') => {
    cy.wait(10000);

    cy.task('getInboxMail', sec)
        .its('html')
        .then((html) => {
            cy.document({ log: false }).invoke({ log: false }, 'write', html);
        });
});

Cypress.Commands.add('getUserEmail', () => {
    cy.wrap(
        new Cypress.Promise((resolve) => {
            cy.task('getUserEmail').then((email) => {
                expect(email).to.be.a('string');
                resolve(email);
            });
        }),
    );
});

These commands:

  1. openInboxMail: Fetches the latest email and writes its HTML content to the document, allowing Cypress to interact with it.
  2. getUserEmail: Retrieves the user email configured for the tests.

Using the Custom Commands

In your Cypress tests, you can now use the custom commands to interact with the email account.

Example Test

describe('Email Tests', () => {
    it('should open the latest email', () => {
        cy.getUserEmail().then((email) => {
            // Use the email address for test purposes
            console.log('User email:', email);
        });

        cy.openInboxMail().then(() => {
            cy.contains('Welcome').should('exist');
        });
    });
});

This example test:

  1. Retrieves the User Email: Logs the user email for debugging or test purposes.
  2. Opens the Latest Email: Fetches and verifies the content of the latest email.

Conclusion

Integrating email account monitoring into Cypress tests using imapflow and mailparser enhances your E2E testing capabilities. This setup allows you to verify email functionality within your application, ensuring that email notifications and related features work as expected. By following the steps outlined in this article, you can seamlessly incorporate email monitoring into your Cypress testing workflow.

Share with your friends

Related posts