permalink | title |
---|---|
/email |
Email Testing |
In End 2 End testing we need to interact with emails. Email delivery can't tested locally or mocked while testing. That's why for an end to end test you need to use a real emails to be sent and real email address to receive that emails.
Setting up an email server can be hard. So we recommend to use a MailSlurp - a service designed for testing emails. It creates disposable mailboxes and provides you an access to those mailboxes via REST API.
You no longer need to open your gmail account in a browser to check for an email!
MailSlurp is a commercial service with a free plan available. To start, create an account at MailSlurp and receive API key to use it. Once received install mailslurp helper from npm:
npm i @codeceptjs/mailslurp-helper --save-dev
Then enable a helper in codecept.conf.js
:
helpers: {
MailSlurp: {
require: '@codeceptjs/mailslurp-helper',
apiKey: '<apiKeyFromMailSlurp>'
}
}
After a helper is added, regenerate TypeScript definitions for auto-completion support:
npx codeceptjs def
MailSlurp allows you to create disposable mailboxes. It means that an email address is created for a one test only and is deleted afterwards. So you can be confident that no other emails are received at that address.
To create a mailbox use I.haveNewMailbox()
command:
// inside async/await function
const mailbox = await I.haveNewMailbox();
mailbox object contains:
id
- which is used in next commandsemailAddress
- randomly generated address of a created mailbox.
See MailSlurp's guide for details.
Mailbox is opened on creation. If you need more than one mailboxes and you want to switch between them use openMailbox
method:
const mailbox1 = await I.haveNewMailbox();
const mailbox2 = await I.haveNewMailbox();
// mailbox2 is now default mailbox
// switch back to mailbox1
I.openMailbox(mailbox);
A last created mailbox will be activated. It means that it will be used by default to check for emails.
After an action that triggers sending an email is performed on a website you should wait for this email to be received. A timeout for waiting an email can be set globally for a helper or for a one call.
Use waitForLatestEmail
function to return the first email from a mailbox:
// to wait for default time (10 secs by default)
I.waitForLatestEmail();
// or specify number of time to wait
I.waitForLatestEmail(30);
To specify the exact email to match use waitForEmailMatching
function:
// wait for an email with partial match in subject
I.waitForEmailMatching({ subject: 'Restore password' });
// wait 30 seconds for email with exact subject
I.waitForEmailMatching({ subject: '=Forgot password' }, 30);
// wait a last email from any address @mysite.com
I.waitForEmailMatching({
from: '@mysite.com', // find anything from mysite
subject: 'Restore password', // with Restore password in subject
});
All wait* functions return a matched email as a result. So you can use it in a test:
const email = await I.waitForLatestEmail();
Please note, that we use
await
to assign email. This should be declared inside async function
An email
object contains following fields:
subject
for
to
body
So you can analyze them inside a test. For instance, you can extract an URL from email body and open it. This is how we can emulate "click on this link" behavior in email:
// clicking a link in email
const email = await I.waitForLatestEmail();
// extract a link by RegExp
const url = email.body.match(/http(s):\/\/(.*?)\s/)[0];
// open URL
I.amOnPage(url);
Assertions are performed on the currently opened email.Email is opened on waitFor
email call, however, you can open an exact email by using openEmail
function.
const email1 = await I.waitForLatestEmail();
// test proceeds...
const email2 = await I.waitForLatestEmail();
I.openEmail(email1); // open previous email
After opening an email assertion methods are available.
seeInEmailSubject
seeEmailIsFrom
seeInEmailBody
dontSeeInEmailBody
And here is an example of their usage:
I.waitForLatestEmail()
I.seeEmailIsFrom('@mysite.com');
I.seeInEmailSubject('Awesome Proposal!');
I.seeInEmailBody('To unsubscribe click here');
More methods are listed in helper's API reference
Use grabAllEmailsFromMailbox
to get all emails from a current mailbox:
const emails = await I.grabAllEmailsFromMailbox();
You can also send an email from an active mailbox:
I.sendEmail({
to: ['[email protected]'],
subject: 'Hello',
body: 'World'
});