Test the user sign up and authentication process in your application using real email addresses. Test your app end to end with disposable inboxes using this guide.

## Background

Email is a key component of most modern applications. It identifies users, let's them sign-up and login, reset passwords and confirm their accounts. Email is important but, strangely, testing processes that rely on email end-to-end can be difficult.

### Email testing APIs

MailSlurp is free to use test [email account API](https://www.mailslurp.com/) that was built to solve this problem. It let's developers create [test email accounts](/guides/email-for-testing-test-email-accounts/) on demand in apps and tests, or using a visual dashboard.

## An example project

In this post we'll use a free MailSlurp account to test a typical user sign-up process end-to-end. To do that we will create test email accounts dynamically during each test and use them to sign up for an example website. The [MailSlurp Playground](/guides/user-signup-playground/) will act as our dummy application: a free WebApp that simulates various modern OAuth2 processes.

### Testing user sign-up

Here is what we'll need to verify in our test

- User can load our application
- User can sign-up using a generated email address
- User receives a confirmation code via email
- User can enter confirmation code and confirm account
- Lastly, user can login and see a welcome screen.

These steps are common for many applications and may reflect a user sign-up process in your own system.

### What does our app look like?

The Playground App is hosted at [https://playground.mailslurp.com](https://playground.mailslurp.com) and is a simple React Application that looks like this:

![test-user-signup](/assets/screenshots/playground/signup.png).

Anyone can sign-up or login to the site. The application was designed with automated testing in mind and simply displays a happy dog upon successful login.

## Testing with MailSlurp

To write an automated test for our sign-up process we need a framework. Any framework will do but we will use Webdriver.io (which is similar to Selenium), Javascript and the [official MailSlurp Javascript SDK](/docs/js/).

> MailSlurp has a REST API and official packages in [Java, PHP, Python, Ruby, C# and more](/docs/).

## Project setup

Let's start by creating a new folder and a few files.

```bash
mkdir signup && cd $_
```

Assuming we have NodeJS installed let's add MailSlurp as a dependency via `npm`.

```bash
echo '{}' > package.json
npm install --save mailslurp-client
```

> **Note**: MailSlurp is free for personal use but you will need an API Key. Get one by [signing-up](https://app.mailslurp.com/sign-up/).

### Add a test framework

Next let's add [Webdriver](http://webdriver.io) to our project. Webdriver goes by the alias `wdio` and splits itself up across several packages. We'll add those now.

```bash
npm install --save @wdio/cli @wdio/local-runner @wdio/mocha-framework @wdio/selenium-standalone-service
```

For wdio to run inside a web browser we need to make one available to it. Here we will use Chrome.

```bash
npm install --save chromedriver wdio-chromedriver-service
```

### Configure Webdriver

Next we need to configure wdio using a wdio.conf.js file in the root of our project. This will tell Webdriver where to look for tests and what browser to use. We want out instance to load the Playground app (see `baseUrl`) and look for tests in a `test` folder:

```javascript
const config = {
  runner: "local",
  path: "/",
  specs: ["test/*.test.js"],
  exclude: [],
  maxInstances: 10,
  capabilities: [
    {
      maxInstances: 5,
      browserName: "chrome",
    },
  ],
  logLevel: "info",
  bail: 0,
  baseUrl: "https://playground.mailslurp.com",
  waitforTimeout: 30000,
  connectionRetryTimeout: 90000,
  connectionRetryCount: 3,
  framework: "mocha",
  services: ["chromedriver"],
  reporters: ["spec"],
  mochaOpts: {
    ui: "bdd",
    timeout: 60000,
  },
};

exports.config = config;
```

### Add a test command

Lastly, we need a way to run out tests one we have written them. For this we can extend the `package.json` scripts property to call wdio. Here's what our `package.json` file looks like altogether:

```json
{
  "scripts": {
    "test": "wdio wdio.conf.js"
  },
  "dependencies": {
    "@wdio/cli": "^5.13.2",
    "@wdio/local-runner": "^5.13.2",
    "@wdio/mocha-framework": "^5.13.2",
    "@wdio/selenium-standalone-service": "^5.13.2",
    "@wdio/spec-reporter": "^5.13.2",
    "chromedriver": "^78.0.1",
    "mailslurp-client": "^6.5.0",
    "wdio-chromedriver-service": "^5.0.2"
  }
}
```

Now when we run `npm test` Webdriver will execute any files ending with `.test.js` in the `test` directory. Speaking of which, let's write some!

## Writing a test

Wdio is configured to find tests in a `test` durectory so let's create that and add a test to it.

```bash
mkdir test
touch test/sign-up.test.js
```

### Defining test requirements

Before we write our test logic let's review what we want to achieve. We want to test that our app (the Playground) has a functioning user sign-up feature (a critical component of any application).
For this we will need to perform the following actions:

- Sign up as a new user
- Confirm the users account
- Login and see a doggy welcome

### Special needs (why we use a email testing API)

Most of these steps are pretty standard for end-to-end testing but sign-up and confirmation are special:

- Sign up will require a **unique email address** each time we run the test
- Confirmation will require that we **fetch and extract a confirmation code** sent to our user's email address

Luckily, MailSlurp helps with all that.

With MailSlurp we can create test email accounts and then send and _receive_ emails from them from within tests. That will allow us to create new email addresses for each test run (so that they are unique and empty) and receive and extract the confirmation code for use in the email confirmation step!

## Generating test email accounts

MailSlurp makes [generating dynamic test email accounts](https://www.mailslurp.com/) on demand easy.

First [obtain your API Key](https://app.mailslurp.com) and configure a MailSlurp client to use it.

```javascript
const MailSlurp = require("mailslurp-client").default;
const apiKey = process.env.API_KEY;
const mailslurp = new MailSlurp({ apiKey });
```

Then to create a new randomized test email address invoke the `createInbox` function.

```javascript
const { emailAddress, id } = await mailslurp.createInbox();
```

> You can specify an address by passing the `emailAddress` parameter and using a custom domain you own. Unspecified email addresses will be randomly assigned under the `@mailslurp.com` domain.

## Testing user sign-up with disposable email addresses

Now that we know how to create email addresses on demand with MailSlurp we can write a test that loads the Playground, creates an email account and then uses it to sign-up.

Here's the first step for our test:

```javascript
const assert = require("assert");

describe("sign up page", () => {
  it("can load playground app", async () => {
    await browser.url("/");
    await browser.setWindowSize(1200, 1200);
  });
});
```

The above loads the Playground - that's it. Next we need to navigate to the sign-up form by clicking a link. Then we assert that we are in the right location. We add the following to the same test:

```javascript
it("can load the sign-up section", async () => {
  await $('[data-test="sign-in-create-account-link"]').then((e) => e.click());
  await $(".sign-up-header-section")
    .then((e) => e.getText())
    .then((text) => assert.strictEqual(text, "Testable Sign Up Form"));
});
```

Let's test this now to see if it works as we expect.

```bash
API_KEY=your-mailslurp-api-key npm run test
```

We should see Chrome launch, the sign-up page load and the test complete with successful output:

```
[chrome  linux #0-0] Running: chrome on linux
[chrome  linux #0-0]
[chrome  linux #0-0] sign up page
[chrome  linux #0-0]    PASS can load playground app
[chrome  linux #0-0]    PASS can load the sign-up section
[chrome  linux #0-0]
[chrome  linux #0-0] 2 passing (607ms)


Spec Files:	 1 passed, 1 total (100% completed) in 00:00:01
```

> If your Chromedriver complains you may need to install a version that matches the version of Chrome on your computer.

## Signing up

Ok, it works. Now for the fun stuff. Let's sign up a new user.

```javascript
let inbox;
let password = "test-password";

it("can sign-up with test email account", async () => {
  // create a new email address for the test run
  inbox = await mailslurp.createInbox();

  // fill out and submit the new user form
  await $('[name="email"]').then((e) => e.setValue(inbox.emailAddress));
  await $('[name="password"]').then((e) => e.setValue(password));
  await $('[data-test="sign-up-create-account-button"]').then((e) => e.click());
});
```

Running that test should fill out a form like below:

![test-sign-up](/assets/screenshots/playground/sign-up-automated.jpg)

## Capturing email confirmation code in tests

So we have successfully signed up a user using the test email address we created. Now we should see a confirmation page that asks us to enter a code that has been emailed to the address that we used.

![confirmation](/assets/screenshots/playground/confirm.png)

> MailSlurp allows use to receive emails in tests!

To enter the confirmation code let's fetch the expected email using MailSlurp, extract the code, and enter it into the form:

```javascript
it("can fetch confirmation code", async () => {
  // fetch the email from mailslurp
  const email = await mailslurp.waitForLatestEmail(inbox.id);

  // verify that it contains the code
  assert.strictEqual(/verification code is/.test(email.body), true);

  // extract the confirmation code
  code = /([0-9]{6})$/.exec(email.body)[1];
});

it("can enter confirmation code and confirm user", async () => {
  await $('[name="code"]').then((e) => e.setValue(code));
  await $('[data-test="confirm-sign-up-confirm-button"]').then((e) => e.click());
});
```

Voila, the test passes, the user is confirmed and we see the sign-in screen. The most important parts of the test above are the lines that fetch the confirmation email and extract the code. The email that is sent looks like this:

![welcome](/assets/screenshots/playground/code.png)

To receive the email in our test we use the `waitForLatestEmail` method and pass the `id` of the inbox that we created during that test run. This will return the first email in the inbox or wait for one to be received.

To extract the verification code we use a regex that matches 6 digits and apply that to the email body.

```javascript
code = /([0-9]{6})$/.exec(email.body)[1];
```



{{LANDING_SHORTCODE:POST_CTA_BANNER:%7B%22title%22%3A%22Check%20the%20confirmation%20email%20customers%20will%20see%22%2C%22content%22%3A%22After%20the%20signup%20test%20receives%20the%20confirmation%20email%2C%20use%20%5Bfree%20email%20render%5D(%2Ftools%2Ffree-email-render%2F)%20and%20device%20previews%20to%20review%20the%20delivered%20template%2C%20links%2C%20image%20behavior%2C%20and%20release%20evidence%20before%20the%20flow%20reaches%20real%20users.%22%2C%22buttonHref%22%3A%22%2Fproduct%2Fdevice-previews%2F%22%2C%22buttonText%22%3A%22Explore%20device%20previews%22%2C%22buttonTheme%22%3A%22blue%22%2C%22image%22%3A%22%2Fassets%2Fhome%2Fdevice-render-devices.png%22%2C%22imageAlt%22%3A%22Email%20preview%20workflow%20across%20supported%20client%20and%20device%20contexts%22%2C%22imageWidth%22%3A%22800%22%2C%22imageHeight%22%3A%22415%22%2C%22imagePosition%22%3A%22%22%7D}}



## Logging in with confirmed account

Lastly, let's test that the confirmed user can sign-in and see a welcome screen. The welcome screen looks a bit like this:

![welcome](/assets/screenshots/playground/welcome.jpg)

Here is the code to login in a verify the happy dog is present:

```javascript
it("can log in with confirmed account", async () => {
  // assert we see the sign in form
  await $('[data-test="sign-in-header-section"]')
    .then((e) => e.getText())
    .then((text) => assert.strictEqual(text, "Sign in to your account"));

  // fill out username (email) and password
  await $('[name="username"]').then((e) => e.setValue(inbox.emailAddress));
  await $('[name="password"]').then((e) => e.setValue(password));

  // submit
  await $('[data-test="sign-in-sign-in-button"]').then((e) => e.click());
});

it("shows the successful greeting", async () => {
  await $('[data-test="greetings-nav-bar"]')
    .then((e) => e.getText())
    .then((text) => assert.strictEqual(/Hello/.test(text), true));
});
```

## In summary

This post demonstrating how you can truly end-to-end test email related processes like user sign-up, email confirmation, and login. It used Webdriver to run the tests but the only required aspect is an email API provider like [MailSlurp](https://www.mailslurp.com/). MailSlurp is free for personal use and will let you and your team test every crucial aspect of your app. Give it a go today!

### Code samples

As always full code samples for this post are available [on GitHub](https://github.com/mailslurp/examples).
