Nightwatch

Info Installation of an example isn't necessary. Should you desire, an example can be had in a GitHub Kanban Repository. It is a simple ReactJS web app with a configuration to run a Nightwatch driven Selenium acceptance test. If you want to run the test locally, see Clone and Run Example Project.

Nightwatch is a pure-JavaScript Selenium client. Nightwatch communicates with a Selenium server using the W3C WebDriver Standard1. The developer writes JavaScript tests using a Behavioral-Driven Development API exposed by Nightwatch.

Simple Test Examples

The following code snippet shows how a developer would start and end a test case on a web page.

var kanban;
module.exports = {
    before: function (client) {
        console.log('Open browser...');
        kaban = client
            .url('http://gkedge.github.io/Kanban/')
            .waitForElementVisible('body', 250);
    },
    after: function (client) {
        console.log('Closing down...');
        client.end();
    },
    ...
}

Line 5-7 waits until the Selenium server detects the <body/> tag in the browser on page-load. Future tests will reference the saved, opened session.

The following code snippet shows two tests on the opened session:

var kanban;
module.exports = {
    before: function (client) {
        console.log('Open browser...');
        // A 'page' assumes a single URL is provided
        // to navigate to.
        kanban = client.page.kanbanPage().navigate();
    },
    after: function (client) {
        console.log('Closing down...');
        client.end();
    },
    'Finding title': function () {
        kanban.assert.title('Kanban app');
    },
    'Adding Kanban Lane': function () {
        kanban.click('@addLaneBtn');
        kanban.waitForElementVisible('@laneOne', 100);
    }
};
  1. The "Finding title" test searches for the title tag on page-load.
  2. The "Adding Kanban Lane" test clicks the 'add-lane' button and detects if the newly added lane appears.

Notice that when the test interacts with a DOM element, it finds it using CSS syntax. See lines 6 & 7 in beforeAfter.js snippet and lines 8 & 9 in the simpleTest.js snippet. This syntax is familiar and natural to web developers. Though CSS has the advantage of being a familiar DOM search syntax, those CSS strings will change over the course of a project. Tests could reference DOM elements many times. Riddling a test suite with copies of the same brittle CSS strings isn't DRY. IOWs: lots of maintenance. Enter PageObject's.

Nightwatch PageObject

PageObject's are a general acceptance testing abstraction. They captures element identifiers into a single object. If an element identifier changes, a single place within it's related PageObject needs maintenance. The test suite stays intact. The 'Page' part of the PageObject name is important. Minimally, each page should have a dedicated PageObject to further ease maintenance. A web page could get sufficiently complex to warrant more than one PageObject; perhaps a PageObject per panel.

The following PageObject abstracts the CSS identifiers for the Kanban page:

module.exports = {
    url     : 'http://localhost:8888',
    elements: {
        page      : 'body',
        addLaneBtn: 'button.add-lane',
        laneOne: 'div.lane[data-lane-num="0"]'
    }
};

kanbanPage captures the 4 CSS identifiers used in our test suite snippets above. Nightwatch's testing API provides fluent sugar to ease access to the PageObject. That sugar makes the name of the PageObject file significant. Here are the tests rewritten using the fluent page API and less brittle element identifiers. Line 7 requires PageObject file named kanbanPage.js:

var kanban;
module.exports = {
    before: function (client) {
        console.log('Open browser...');
        // A 'page' assumes a single URL is provided
        // to navigate to.
        kanban = client.page.kanbanPage().navigate();
    },
    after: function (client) {
        console.log('Closing down...');
        client.end();
    },
    'Finding title': function () {
        kanban.assert.title('Kanban app');
    },
    'Adding Kanban Lane': function () {
        kanban.click('@addLaneBtn');
        kanban.waitForElementVisible('@laneOne', 100);
    }
};

Easy Peasy

These tests are not hard to write. See Complete Test for the complete Kanban web application acceptance test suite. See KanbanPage for the Kanban PageObject.

1. The W3C standard was formerly known as the JSON Wire Protocol