Hello everyone!
Reading emails in automated tests is a trick that you might need to know how to do in a lot of the projects. Here’s why and how to deal with it…
Well, if the system sends emails - you might want to verify that they are being sent and the content is right, including clickable links.
So these are the usual scenarios when you need this:
Sign up.
A lot of platforms send a confirmation email once you create an account, and you need to click a confirmation link from the email.
Invoices.
If your app does any payments - they usually send a cheque or invoice via email, so you might want to see if their contents are correct too.
Results.
Like medical test results. In my experience - some hospitals send an email with test results once they are done (or at least a link to a personal page where you can view the report).
…
Of course, this is not the complete list - these are just the use cases I’ve met the most in my career.
Failing to verify these scenarios might lead to users not getting emails or getting the wrong information in emails. In one of the projects, it helped us find early an expired SendGrind token.
Reading emails is a tricky thing to do, but not an impossible one.
Early email clients were using POP3 to fetch emails from the server, but there’s a small problem - it deletes the emails from the server once they are downloaded.
Later, IMAP protocol came in - it allows you to simply read emails from the server.
The problem is -
On the other hand, some services like Gmail provide a REST API to manipulate your emails, but there’s another problem - the documentation and its libraries are not really that user-friendly (especially for those who don’t work with email testing much).
This is where gmail-getter comes in - an npm library that allows you to read emails and even open them in your browser if you use browser automation tools like Playwright.
First thing first - you need to install the package in your project:
npm install gmail-getter
To log into Gmail API, you need to obtain credentials: a Client ID, a Client Secret, and a Refresh token. These credentials let you get an Access token, which is required in further requests (like getting a list of emails or a single email, etc.).
Steps to go:
Create a project in Google Cloud Console.
Create OAuth credentials in the API & Services section (preferably, select Desktop app there if you need it for automated tests) and download it.
Enable the Gmail API.
Obtain a Refresh token.
To get a Refresh token - simply execute a command in a project root:
npx gmail-getter get-refresh-token
(or anywhere else if you've got the package installed globally)
get-refresh-token
You must put the credentials.json
file in a place where you will execute the command.
⚠️ credentials file name is case-sensitive ⚠️
Once the configuration is done, you must get an Access token in your automated tests. I’d say that the best place for it is a global setup (a function that executes before the test run starts).
So, it’ll be something like this:
import {getToken} from 'gmail-getter'
export default async function globalSetup() {
process.env['ACCESS_TOKEN'] = await getToken(
process.env.CLIENT_ID!,
process.env.CLIENT_SECRET!,
process.env.REFRESH_TOKEN!
)
}
The example above uses environment variables, for which you will definitely need to install the dotenv package as well.
But, if you wanna keep things simple - you can use this snippet wherever you need the token to be accessible from:
const accessToken = await getToken(
'<put-your-client-id-here>',
'<put-your-client-secret-here>',
'<put-your-refresh-token-here>'
)
Right now, Gmail’s REST API uses its own query language to find the email you need:
const email = await checkInbox(accessToken!, 15000, 1500, 'from:squier7 subject:Test!')
The command above returns you an email object, but you still need to get either its contents or a link. Replace from:squier7 subject:Test!
to your own query following the syntax from the link above ☝️
You can parse a link using a regex:
const link = parseLinkFromHtml(email!, /(https:\/\/)(\S*)(gmail-getter)([\w\/\?\=\-]*)/im)
Replace /(https:\/\/)(\S*)(gmail-getter)([\w\/\?\=\-]*)/im
with your own regular expression ☝️
OR get the whole HTML content of the email, and render it in your browser:
import {getToken, parseHtml} from 'gmail-getter'
import {test} from '@playwright/test'
test('Render an email', async ({page}) => {
const accessToken = await getToken(
'<put-your-client-id-here>',
'<put-your-client-secret-here>',
'<put-your-refresh-token-here>'
)
const email = await checkInbox(accessToken!, 15000, 1500, 'from:squier7 subject:Test!') // get an email
const html = parseHtml(email!) // parse HTML from the email
await page.setContent(html) // render the email in the browser
})
I think it’s pretty obvious now that working with emails in automated tests might be tricky! But knowing these tricks makes things much easier.
You might still go through some other email services or try IMAP, but I guarantee you - it won’t be as easy as it is in this guide, as you’d need to create a helper of your own, like gmail-getter provided here.
You can find the Playwright example on GitHub. Cypress example too.