MailSlurp Cypress Plugin
Official MailSlurp email plugin for Cypress JS. Create real test email accounts. Send and receive emails, SMS, and attachments in Cypress tests. For examples and usage see the standard MailSlurp library.
Tutorial
Test email and SMS/TXT messages in Cypress
With MailSlurp and Cypress you can:
- create unlimited, disposable email addresses for testing
- send and receive emails in tests
- send and receive SMS messages in tests
- capture outbound emails with fake mailservers
- extract email verification codes and OTP magic links
Example
it('can sign up using throwaway mailbox', function () {
cy.mailslurp().then(function (mailslurp) {
cy.visit('/');
cy.then(() => mailslurp.createInbox())
.then((inbox) => {
cy.wrap(inbox.id).as('inboxId');
cy.wrap(inbox.emailAddress).as('emailAddress');
})
cy.get('[data-test=sign-in-create-account-link]').click()
cy.then(function () {
cy.get('[name=email]').type(this.emailAddress)
cy.get('[name=password]').type('test-password')
return cy.get('[data-test=sign-up-create-account-button]').click();
})
cy.then({
timeout: 60_000
}, function () {
return mailslurp
.waitForLatestEmail(this.inboxId, 60_000, true)
.then(email => mailslurp.emailController.getEmailContentMatch({
emailId: email.id,
contentMatchOptions: {
pattern: 'Your Demo verification code is ([0-9]{6})'
}
}))
.then(({matches}) => cy.wrap(matches[1]).as('verificationCode'))
});
cy.then(function () {
cy.get('[name=code]').type(this.verificationCode)
cy.get('[data-test=confirm-sign-up-confirm-button]').click()
cy.get('[data-test=username-input]').type(this.emailAddress)
cy.get('[data-test=sign-in-password-input]').type('test-password')
return cy.get('[data-test=sign-in-sign-in-button]').click();
})
cy.get('h1').should('contain', 'Welcome');
});
});
Quick links
Install
Ensure you have Cypress installed first then run:
npm install --save-dev cypress-mailslurp
Then include the plugin in your cypress/support/index.{js,ts}
file.
import 'cypress-mailslurp';
[!IMPORTANT]
You must import/require cypress-mailslurp
in your support file cypress/support/e2e.ts
or cypress/support/index.{js,ts}
Configuration
See the example project for example code.
API Key
MailSlurp is free but requires an API Key. Get yours by creating a free account.
Set the environment variable CYPRESS_MAILSLURP_API_KEY
or use the cypress.json
file env
property:
Environment variable
For Mac/Linux set the CYPRESS_MAILSLURP_API_KEY
environment variable:
CYPRESS_MAILSLURP_API_KEY=your-api-key cypress run
For Windows machines use the Powershell format $env:CYPRESS_MAILSLURP_API_KEY
$env:CYPRESS_MAILSLURP_API_KEY=your-api-key;
cypress run;
Cypress env property
You can also configure Cypress using the config format.
{
"env": {
"MAILSLURP_API_KEY": "your-mailslurp-api-key"
}
}
Configure dynamically
You can also pass the cy.mailslurp()
function a config containing an apiKey
like so:
cy.mailslurp({ apiKey: 'YOUR_KEY' })
Timeouts
MailSlurp requires timeouts to wait for inbound emails. You can set global timeouts in cypress.json
:
{
"defaultCommandTimeout": 30000,
"responseTimeout": 30000,
"requestTimeout": 30000
}
Or you can set timeouts on a per-method basis using the first argument as a timeout config:
cy.then({ timeout: 60_000 }, () => { })
Typescript support
MailSlurp adds the mailslurp
command to the Cypress cy
object. Include the type definition reference comment in your test file or support index.ts:
Or define the type yourself like so:
import { MailSlurp } from "mailslurp-client";
declare global {
namespace Cypress {
interface Chainable {
mailslurp: () => Promise<MailSlurp>;
}
}
}
Usage
The Cypress MailSlurp plugin provide one simple command attached to the Cypress object: cy.mailslurp()
. This method returns a MailSlurp client instance that has all the same methods and properties as the official MailSlurp client. Use the command with the then()
method to access the instance:
cy.mailslurp().then(mailslurp => mailslurp.createInbox() )
You can test that you have setup MailSlurp correctly in a test like so:
describe('sign up using disposable email', function () {
it('can set config', () => {
cy.mailslurp({ apiKey: 'YOUR_KEY' })
Common methods
The client chained by the cy.mailslurp()
has all the same methods and properties as the official MailSlurp client. See the Javascript documentation for a full API reference or see the examples below.
The MailSlurp client has a number of convenience methods and also exposes the full MailSlurp API as controllers. See the class reference for full method documentation.
Create email address
You can create test email accounts with MailSlurp by creating inboxes. Inboxes have an id
and an emailAddress
. Save the id
for later use when fetching or sending emails.
await cy.mailslurp()
.then((mailslurp: MailSlurp) => mailslurp.createInboxWithOptions({}))
.then(inbox => {
expect(inbox.emailAddress).to.contain("@mailslurp")
cy.wrap(inbox.id).as('inboxId')
cy.wrap(inbox.emailAddress).as('emailAddress')
})
Send emails
To send emails in Cypress tests first create an inbox then use the sendEmail
method.
await cy.mailslurp()
.then((mailslurp: MailSlurp) => mailslurp.sendEmail(this.inboxId, {
to: [this.emailAddress ],
subject: 'Email confirmation',
body: 'Your code is: ABC-123',
}))
Receive emails in tests
Use the waitFor
methods to wait for emails for an inbox. See the email object docs for full properties.
cy.log("Waiting for email")
await cy.mailslurp().then({
timeout: 60_000,
}, (mailslurp: MailSlurp) => mailslurp.waitForLatestEmail(this.inboxId, 60_000, true))
.then(email => {
expect(email.subject).toContain('Email confirmation')
const code = email.body.match(/Your code is: (\w+-\d+)/)[1]
expect(code).toEqual('ABC-1223')
})
Accessing more methods
To access all the MailSlurp methods available in the REST API and Javascript Client use the controllers on the mailslurp instance.
cy.mailslurp().then(mailslurp => mailslurp.attachmentController.uploadAttachment({
base64Contents: fileBase64Encoded,
contentType: 'text/plain',
filename: basename(pathToAttachment)
}))
Storing values between tests
Cypress has a unique async nature. To use MailSlurp effectively with Cypress chain your commands using then()
or store results in wrapped aliases using wrap()
and as()
.
before(function() {
return cy
.mailslurp()
.then(mailslurp => mailslurp.createInbox())
.then(inbox => {
cy.wrap(inbox.id).as('inboxId');
cy.wrap(inbox.emailAddress).as('emailAddress');
});
});
it('can access values on this', function() {
expect(this.emailAddress).to.contain('@mailslurp');
});
[!NOTE]
Using wrap
to store values across test methods requires you to use function
syntax instead of () =>
arrow syntax. This ensure that this
is dynamically scoped and includes the aliased variables.
Example test
Here is an example of testing user sign up on a demo application hosted at playground.mailslurp.com.
It creates a new MailSlurp inbox before all tests and saves the inbox.id
and inbox.emailAddress
to a shared text context using the cy.wrap().as()
methods.
It then loads the demo application, fills out a sign up form using the email address and receives a user confirmation code.
We wait for the email to arrive using the waitForLatestEmail
method and then extract a confirmation code that can be submitted to the app to confirm the user.
describe('user sign up test with mailslurp plugin', function() {
before(function() {
return cy
.mailslurp()
.then(mailslurp => mailslurp.createInbox())
.then(inbox => {
cy.wrap(inbox.id).as('inboxId');
cy.wrap(inbox.emailAddress).as('emailAddress');
});
});
it('01 - can load the demo application', function() {
expect(this.emailAddress).to.contain('@mailslurp');
cy.visit('/');
cy.title().should('contain', 'React App');
});
it('02 - can sign up using email address', function() {
cy.get('[data-test=sign-in-create-account-link]').click();
cy.get('[name=email]')
.type(this.emailAddress)
.trigger('change');
cy.get('[name=password]')
.type('test-password')
.trigger('change');
cy.get('[data-test=sign-up-create-account-button]').click();
});
it('03 - can receive confirmation code by email', function() {
cy.mailslurp()
.then(mailslurp =>
mailslurp.waitForLatestEmail(this.inboxId, 30000, true)
)
.then(email => /.*verification code is (\d{6}).*/.exec(email.body!!)!![1])
.then(code => {
cy.get('[name=code]')
.type(code)
.trigger('change');
cy.get('[data-test=confirm-sign-up-confirm-button]').click();
});
});
it('04 - can sign in with confirmed account', function() {
cy.get('[data-test=username-input]')
.type(this.emailAddress)
.trigger('change');
cy.get('[data-test=sign-in-password-input]')
.type('test-password')
.trigger('change');
cy.get('[data-test=sign-in-sign-in-button]').click();
});
it('05 - can see welcome screen', function() {
cy.get('h1').should('contain', 'Welcome');
});
});
More examples
See the Cypress example test suite for real tests that use this plugin.