HomePosts

Introduction to end-to-end Nightwatch Testing

NextJs
Web Dev
Nightwatch

Fri Dec 30 2022

Introduction

If you wanted a quick and easy introduction to Nightwatch this is the post for you! Nightwatch is an end-to-end testing tool for frontend applications. Setting up Nightwatch will allow you makes change with confidence as you will be able to add end-to-end tests to cover your business-critical flows.

Setting up Nightwatch

Installing the Package

In order to be able to use Nightwatch the package must be installed first. You can do this by the following command.

npm install nightwatch chromedriver --save-dev

Setting up the Folder Structure (Optional)

Secondly, we will need to create the folder structure within your repository to allow the easy addition of end-to-end tests and to allow all nightwatch related files to exist in an easy to find place. This section is marked as optional since you can easily change this to reflect your desired folder structure; just remember to update any paths that are mentioned in this file to reflect the structure you have adopted. 

We will now create the folder structure where a folder called test will be created which includes a folder named e2e. Within the e2e folder a folder named components and tests should be created which will come on to later regarding their meaning. See below example for the structure.  

test/
  e2e/
    components/
    tests/

Add Running Nightwatch to Package.json Scripts

In order to be able to run Nightwatch E2Es via the command line add to the package.json within the script property the following so that we can call nightwatch using npm run.

"e2e": "./node_modules/.bin/nightwatch -c test/e2e/nightwatch.conf.js",

Create the Nightwatch Config

Create a file named nightwatch.conf.js this file will be used to tell nightwatch what to do when you run your tests against specific browsers, what variables to swap out, and the path to file your global variables, tests folder and pages folder.

/* eslint-disable no-use-before-define */
/* eslint-disable no-empty */
/* eslint-disable global-require */

const Services = {}; loadServices();
const chromeConfiguration = {
    test_workers: false,
    desiredCapabilities: {
        screenshots: {
            enabled: false,
            path: 'screens',
            on_failure: true,
        },
        browserName: 'chrome',
        javascriptEnabled: true,
        acceptSslCerts: true,
        acceptInsecureCerts: true,
        chromeOptions: {
            args: [
                '--ignore-certificate-errors',
            ],
        },
    },
    webdriver: {
        start_process: true,
        port: 9515,
        server_path: (Services.chromedriver ? Services.chromedriver.path : ''),
        cli_args: [],
    },
};

module.exports = {
    // An array of folders (excluding subfolders) where your tests are located;
    // if this is not specified, the test source must be passed as the second argument to the test runner.
    src_folders: ['./test/e2e/tests/'],
    // See https://nightwatchjs.org/guide/working-with-page-objects/
    page_objects_path: './test/e2e/components/',
    // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
    custom_commands_path: '',
    // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions
    custom_assertions_path: '',
    // See https://nightwatchjs.org/guide/#external-globals
    globals_path: './globalsModule.js',
    test_settings: {
        default: {
            disable_error_log: false,
            launch_url: 'http://localhost:3000/', 
            ...chromeConfiguration,
        },
    },
};

function loadServices() {
    try {
        Services.chromedriver = require('chromedriver');
    } catch (err) { }
}

Note that the above snippet expects the tests and components folder to exist within the "test/e2e/" folder.

Create the Globals File

The globals file allows you to change default values for nightwatch. Such as in the below file we have increased the time that will be given when waiting for a condition to be met and when poll interval is used. The file name should be "globalsModule.js"

module.exports = {
    // this will overwrite the default polling interval (currently 500ms) for waitFor commands
    waitForConditionPollInterval: 1000,
    // default timeout value in milliseconds for waitFor commands and implicit waitFor value for
    waitForConditionTimeout: 60000,
};

Creating The First Test

Lets create a test file that exists within the tests folder named "Homepage.js". In the test we will define the first test and ensure that the body is accessible. This is the most basic of an E2E test and will ensure that the homepage is available and that the body is accessible. 

module.exports = {
    'Homepage Available': function (browser) {
        browser
            .url('http://localhost:3000')
            .waitForElementVisible('body', 1000)
            .end();
    }
};

You can see additional Nightwatch commands here

In a later post we will look into using Components/Pages to make your tests contain less duplication and to ensure you only need to change one place for tests that cover simple areas. On to running Nightwatch

Running the Tests

By running the following command Nightwatch will start running through the tests. You should be able to see them run, if you don't want to see them you can use --headless or look into running your tests with Browserstack. This works especially well with tests running through CI/CD

npm run e2e

Assuming all is well you should now see your tests working successfully. Ensure any references in the code are updated to your changes - such as the directory changes or serving your app from a different url. 

Here is a snippet of the tests ran 

[Homepage] Test Suite
=====================
ℹ Connected to localhost on port 9515 (1172ms).
  Using: chrome (92.0.4515.159) on Mac OS X platform.

✔ Running Homepage Available:

✔ Element <body> was visible after 16 milliseconds.

OK. 1 assertions passed. (1.08s)