Why Use Nightwatch?
Nightwatch.js is an open-source, Node.js-powered end-to-end testing framework that simplifies browser automation. It uses the WebDriver protocol to interact with web applications, making it a popular choice for functional and UI testing. If your team needs a reliable tool for cross-browser testing or seamless CI/CD integration, Nightwatch.js is an excellent option. It combines beginner-friendly syntax with powerful features, making it easy to adopt while still capable of handling complex testing scenarios. If you're familiar with Selenium or WebDriver, you'll find it even more intuitive.
Here are some of its advantages:
- Simple syntax – Nightwatch.js offers an easy-to-read syntax, making test scripts more maintainable, even for teams new to end-to-end testing.
- Built-in test runner & assertions – Nightwatch.js comes with a built-in test runner and assertion library, making it easier to write and validate authentication tests without extra dependencies.
- Built-in WebDriver management – Unlike some frameworks that require manual WebDriver setup, Nightwatch.js automatically manages drivers for browsers like Chrome, Edge, Safari, and Firefox.
- Parallel test execution: Supports parallel testing via test workers (distributing test files across processes) and multiple environments (running tests across different browsers). From v1.7, you can combine both for maximum efficiency.
- Supports real browsers and mobile testing: Nightwatch.js runs tests on real browsers, including Chrome, Firefox, Edge, and Safari, using W3C-compliant WebDriver. Additionally, Nightwatch.js stands out with built-in support for testing native mobile apps—something not offered by many competing frameworks.
- Seamless integrations: Works with popular test runners like Mocha, Cucumber, and Jest, allowing flexibility in writing and structuring tests. For CI/CD, it supports tools like GitHub Actions, Jenkins, and CircleCI, making it easy to automate tests as part of your deployment pipeline.
Email-based authentication methods
Email-based authentication methods provide a secure and convenient way for users to log in, verify their identities, or reset their credentials. By sending links or codes directly to users' inboxes, these methods eliminate the need for traditional passwords, reducing security risks like credential stuffing and phishing attacks. Below are some of the most common email-based login methods:
Magic link login
Magic link login is a passwordless authentication method that enhances security and user experience. Users simply enter their email address, receive a unique login link, and click it to gain access. This approach eliminates the hassle of remembering passwords and mitigates risks associated with weak or reused credentials.
One-Time Password (OTP) via Email
This method requires users to enter their email address and receive a time-sensitive one-time password (OTP) in their inbox. The user then enters this OTP to verify their identity. OTPs are widely used in:
- Two-Factor Authentication (2FA) – As an additional layer of security alongside a password.
- Passwordless authentication – Replacing passwords entirely for better security.
Email-based account verification
Common during new account sign-ups, password resets, and sensitive account changes, this method requires users to confirm their email address by clicking a verification link. This step ensures that the user has access to the provided email and prevents fraudulent account creation.
Implementing email authentication methods doesn’t have to be complicated, thanks to a range of tools that handle token generation, email delivery, and security best practices. Services like Auth0, Firebase Authentication, and AWS Cognito offer built-in solutions for magic links, OTPs, and email verification. On the email-sending side, providers like SendGrid, Postmark, Mailgun, and Amazon SES ensure reliable delivery, helping authentication emails reach inboxes quickly and securely.
Why use testmail.app?
Sending authentication emails is just one part of the process—ensuring they’re received and working as expected is just as important. If your authentication emails don’t arrive, have broken links, or fail to validate OTPs, users get locked out—that’s a problem. Testing email-based login flows ensures everything works before issues reach production.
That’s where testmail.app comes in. It’s a simple tool for developers and QA teams to test email workflows in any environment, including CI/CD pipelines. You can generate disposable test emails, fetch messages via API, and verify OTP delivery instantly. That means you can easily integrate email testing into your deployment process, catching issues before they hit production.
For end-to-end testing, you can pair Testmail.app with tools like Nightwatch.js to automate login flow checks, so you know emails are sent and working every time.
Get started with Nightwatch.js
Setting up Nightwatch.js is easy, even for beginners. Here’s how to get started:
Install Node.js
If you don’t have Node.js installed, download and install it from nodejs.org.
Initialize your project
Open your terminal and create a new directory for your project. Inside the project directory, run:
npm init -y
Install Nightwatch.js
npm install nightwatch --save-dev
Install a WebDriver (e.g., ChromeDriver)
You’ll also need to install the appropriate WebDriver for the browser you want to test. For example, to use Chrome, install chromedriver:
npm install chromedriver --save-dev
Configure Nightwatch.js
Create a nightwatch.conf.js
configuration file in your project’s root directory. Here’s an example configuration:
module.exports = {
src_folders: ['tests'], // The location of your test files
webdriver: {
start_process: true,
server_path: require('chromedriver').path, // Path to chromedriver
port: 9515
},
test_settings: {
default: {
desiredCapabilities: {
browserName: 'chrome'
}
}
}
};
Write your test
Create a folder called tests
, and inside it, create a file like signupTest.js
:
Run your Test
To run your tests, execute the following command:
./node_modules/.bin/nightwatch
How to test email-based authentication with testmail.app and Nightwatch.js?
Here’s a simple step-by-step process to test email login using testmail.app and Nightwatch. Below, you’ll find a code example demonstrating the same.
- Setup the test environment: Ensure you have the necessary environment variables set up for your testmail.app API key and namespace. These will be used to interact with the testmail.app API and fetch emails.
- Initiate signup: Open the signup or login page where users enter their email address. Have the test user enter their email address and submit the form, triggering the sending of an email with a verification link or OTP.
- Verify email delivery: Use the Testmail API to fetch the email sent to the test inbox. Once the email is fetched, check key details like the subject and sender to ensure they match the expected values
- Extract the link/OTP: Extract the verification link or OTP from the email content. This link should redirect to a page where the user can complete their sign-up or login process.
- Error handling: In case of any issues (e.g., undelivered emails or broken links), capture the error and handle it accordingly, ensuring the test fails if something goes wrong.
How to set up testmail.app for email testing?
To start testing emails, first, sign up for a testmail.app account. Once your account is set up, configure your environment with the following variables:
- TESTMAIL_APIKEY – API keys are required to access the Testmail API and are authorized to interact with one or more namespaces. You can configure API key permissions in your console.
- TESTMAIL_NAMESPACE – A unique identifier for your test inbox. Think of a namespace as a collection of mailboxes—it supports an unlimited number of email addresses.
These variables allow you to interact with the Testmail API, retrieve test emails, and extract key verification details like OTPs or magic links.
To get the Testmail credentials:

Testmail receives emails at the address format {namespace}.{tag}@inbox.testmail.app.
testmail.app APIs
Testmail.app provides two API options:
- JSON API – easy to use and supports essential email querying features
- GraphQL API – offers more advanced filtering, field selection, and sorting capabilities.
The table below highlights the key features of each API to help you decide which one best fits your needs.
Feature | Simple JSON API | GraphQL API |
---|---|---|
Basic Filters Filter emails by namespace, tag, tag prefix, or timestamp range. |
✅ | ✅ |
Pagination Use limit and offset parameters to retrieve emails in batches. |
✅ | ✅ |
Spam Reports Check spam score and spam report details. |
✅ | ✅ |
Live Queries Wait for new incoming emails in real time. |
✅ | ✅ |
Select Specific Fields Retrieve only the fields you need instead of the full email data. |
❌ | ✅ |
Advanced Filters Filter emails by sender, subject, body content (text or HTML), and more. |
❌ | ✅ |
Custom Sorting Sort results in a custom order (default is newest first). |
❌ | ✅ |
Querying the inbox
Testmail.app receives emails at {namespace}.{tag}@inbox.testmail.app
, where {namespace}
is your unique identifier (found in your console), and {tag}
can be any value you choose.
Namespaces: A namespace acts as a collection of mailboxes, allowing unlimited email addresses under it. For example, if your namespace is acmeinc
, emails sent to [email protected]
and [email protected]
will both be received in the acmeinc
namespace—each distinguished by its respective tag (hello
and hey
).
Tags: Tags provide flexibility in generating dynamic email addresses. You can create unique addresses on the fly by assigning different tags. For instance, if you want to test user signups, you could use [email protected]
for John and [email protected]
for Albert. You can then retrieve their emails individually using the tag filter or fetch all emails under the acmeinc
namespace in one query.
There’s just one query you need: the inbox query. The API returns a result object with the following structure:
"result": "success"
or"result": "fail"
: tells you whether the query was successful or not"message": null
or"message":
: tells you why the query failed (if it failed) or provides helpful warnings"count":
: tells you the number of emails that matched your query"limit":
: tells you the number of emails returned in this request (see limit)"offset":
: tells you the number of emails skipped"emails": [
: array of emails]
Code example: Automating signup email verification
This Nightwatch.js test script verifies the email-based signup flow using testmail.app. The example below uses the JSON API. To explore all API features and options, check out the documentation.
The Testmail.app JSON API endpoint is https://api.testmail.app/api/json
, requiring an API key (&apikey=YOUR_APIKEY
) and a namespace (&namespace=YOUR_NAMESPACE
) for authentication. It only supports HTTP GET requests, so POST requests won't work. To make the response more readable, you can add &pretty=true
as an optional parameter.
First, we'll load the signup page and fill in a dynamically generated testmail.app email address. Once the form is submitted, we’ll use the testmail.app API to fetch the verification email. We'll then extract the verification link from the email and navigate to it, ensuring the user is redirected to the expected page.
/**
* Required environment variables: TESTMAIL_APIKEY and TESTMAIL_NAMESPACE
*/
require('dotenv').config();
const axios = require('axios');
const Chance = require('chance');
const chance = new Chance();
const NAMESPACE = process.env.TESTMAIL_NAMESPACE;
const TAG = chance.string({ length: 12, pool: 'abcdefghijklmnopqrstuvwxyz0123456789' });
const ENDPOINT = `https://api.testmail.app/api/json?apikey=${process.env.TESTMAIL_APIKEY}&namespace=${process.env.TESTMAIL_NAMESPACE}&tag=${TAG}`;
const startTimestamp = Date.now();
module.exports = {
'Load Signup Page': function (browser) {
browser.url('http://your-app.com/signup').waitForElementVisible('body', 1000);
},
'Signup with Testmail Email': function (browser) {
browser
.url('http://your-app.com/signup')
.waitForElementVisible('body', 1000)
.setValue('#email', `${NAMESPACE}.${TAG}@inbox.testmail.app`)
.click('#signup-button')
.waitForElementVisible('#confirmation-message', 5000); // Adjust confirmation element
},
'Check Email Details and Click Link': async function (browser) {
const response = await axios.get(`${ENDPOINT}×tamp_from=${startTimestamp}&livequery=true`)
const verificationEmail = response.data.emails[0];
const verificationLink = verificationEmail.text.match(/https?:\/\/[^\s/$.?#].[^\s]*/)[0];
browser
.url(verificationLink)
.waitForElementVisible('body', 10000)
}
};
The following output is shown in the console after running the above test:

Common challenges in automated email testing
Testing email logins can be tricky due to various security measures, unexpected responses, and edge cases that might not occur during regular manual testing.
Security measures (CAPTCHA and ReCAPTCHA)
CAPTCHA systems are designed to differentiate between human users and automated bots, which can impede automated testing efforts. When a CAPTCHA is present, automated scripts may be unable to proceed without manual intervention.
How to handle it:
- Disable CAPTCHA in test environments by whitelisting test accounts or using developer keys for reCAPTCHA.
- If disabling CAPTCHA isn’t possible, mock authentication requests using API calls instead of UI-based logins.
Email delivery delays or failures
Automated email login testing sometimes requires checking whether a confirmation or password reset email is delivered. Email delivery can be delayed, fail to arrive, or end up in spam, which can lead to tests failing or timing out.
How to handle it:
- Retry with polling: Implement a loop that checks for new emails every few seconds until a timeout threshold is reached. Instead of constant polling, you can use testmail.app’s Live Query feature to wait for new emails in real-time. While most emails arrive quickly, some can take minutes or even days due to server retries after failed delivery attempts. To minimize build timeouts, set a reasonable threshold in your test environment.
- Check spam filters: Properly format emails with SPF, DKIM, and DMARC to avoid spam issues. testmail.app helps by providing spam scores, SPF/DKIM checks, and detailed spam reports to catch deliverability problems early.
- Use dedicated test inboxes: Services like testmail.app allow for better control over test emails, reducing the risk of lost messages.
Frequent UI changes
Login pages often undergo design or feature updates, causing test scripts to break. Regular maintenance is needed to keep up with UI changes.
How to handle it:
- Use stable locators: Instead of relying on element IDs or class names, use more robust selectors like data attributes (
data-testid
) or XPath expressions that adapt to changes. - Implement page object models (POM): Abstract UI interactions into reusable methods, so tests only need small updates when the UI changes.
- Run visual regression tests: Use tools like Percy or Applitools to catch unintended UI changes before they break automation.
Mobile testing challenges
Many users retrieve OTPs or verification links on mobile devices, which introduces issues related to layout, responsiveness, and native email app behaviors.
How to handle it:
- Test across multiple devices and clients: Use real devices or emulators for iOS and Android to check email rendering in both webmail and native apps.
- Validate email responsiveness: Ensure emails use mobile-friendly HTML and CSS for consistent display.
- Use mobile automation frameworks: Tools like Appium can automate interactions with native email apps.