What is Nightwatch?

Nightwatch.js is an automated testing framework for web applications and websites, written in Node.js and using the Selenium WebDriver API.

It is a complete browser automation (End-to-End) solution which aims to simplify the process of setting up Continous Integration and writing of automated tests.

Nightwatch got its name from the famous painting The Night Watch by Dutch painter Rembrandt van Rijn. The masterpiece is prominently displayed in the Rijksmuseum, in Amsterdam - The Netherlands.

Overview of Selenium

Selenium is a very popular and comprehensive set of tools for browser automation, initially written for Java but now with support for most programming languages.

Selenium's main projects are:

Nightwatch uses the Selenium WebDriver, specifically the WebDriver Wire Protocol to perform the browser automation related tasks.

Theory of Operation

Nightwatch works by sending HTTP requests to the Selenium server with the right parameters and interpreting the response. The restful API protocol is defined by the Selenium JsonWireProtocol. See below for an example workflow for browser initialization.

Theory of Operation

Most of the times, Nightwatch needs to send at least 2 requests to the Selenium server in order to perform a command or assetion, the first one being the request to locate an element given a CSS selector (or Xpath expression) and the next to perform the actual command/assertion on the given element.

Install Node.js

From nodejs.org:

"Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices."

There are installation packages and instructions for most major Operating systems on its website nodejs.org. Remember to install also the npm tool, which is the node package manager and is distributed with the Node.js installer.

Install Nightwatch

To install the latest version using the npm command line tool, run the following:

$ npm install nightwatch

To make nightwatch runner available globally in your system, add the -g option after npm install and sudo if you're on Mac OS X / Linux or other Unix based OS.

Running the Selenium Server

The Selenium WebDriver server is simply a Java servlet which runs separately on the machine with the browser you want to test.

Download Selenium

Download the latest version of the selenium-server-standalone-{VERSION}.jar file from the Selenium downloads page and place it on the computer with the browser you want to test. In most cases this will be on your local machine and typically inside your project's source folder.

A good practice is to create a separate subfolder (e.g. bin) and place it there as you might have to download other driver binaries if you want to test multiple browsers.

Running Selenium Automatically

If the server is on the same machine where Nightwatch is running, it can be started/stopped directly by the Nightwatch Test Runner.

Running Selenium Manually

To run the selenium server manually, from the directory with the jar run the following:

$ java -jar selenium-server-standalone-{VERSION}.jar

More info about running the Selenium server can be found here:
http://code.google.com/p/selenium/wiki/RemoteWebDriverServer

For viewing all the run-time options, run the previous command adding the -help:

$ java -jar selenium-server-standalone-{VERSION}.jar -help

The test runner expects a configuration file to be passed, using by default a nightwatch.json file from the current directory, if present. Let's create one in the project's root folder.

The nightwatch.json file will look like this:

{
  "src_folders" : ["tests"],
  "output_folder" : "reports",
  "custom_commands_path" : "",
  "custom_assertions_path" : "",
  "page_objects_path" : "",
  "globals_path" : "",

  "selenium" : {
    "start_process" : false,
    "server_path" : "",
    "log_path" : "",
    "host" : "127.0.0.1",
    "port" : 4444,
    "cli_args" : {
      "webdriver.chrome.driver" : "",
      "webdriver.ie.driver" : ""
    }
  },

  "test_settings" : {
    "default" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4444,
      "selenium_host"  : "localhost",
      "silent": true,
      "screenshots" : {
        "enabled" : false,
        "path" : ""
      },
      "desiredCapabilities": {
        "browserName": "firefox",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      }
    },

    "chrome" : {
      "desiredCapabilities": {
        "browserName": "chrome",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      }
    }
  }
}

Basic settings

Name type default description
src_folders string|array none An array of folders (excluding subfolders) where the tests are located.
output_folder
Optional
string tests_output The location where the JUnit XML report files will be saved.
custom_commands_path Optional string|array none Location(s) where custom commands will be loaded from.
custom_assertions_path Optional string|array none Location(s) where custom assertions will be loaded from.
page_objects_path
Optional since v6.0.1
string none Location(s) where page object files will be loaded from.
globals_path
Optional since v0.4.8
string none Location of an external globals module which will be loaded and made available to the test as a property globals on the main client instance.

Globals can also be defined/overwritten inside a test_settings environment.
selenium
Optional
object An object containing Selenium Server related configuration options. See below for details.
test_settings object This object contains all the test related options. See below for details.
live_output
Optional
boolean false Whether or not to buffer the output in case of parallel running. See below for details.
disable_colors
Optional
boolean false Controls whether or not to disable coloring of the cli output globally.
parallel_process_delay
Optional
integer 10 Specifies the delay(in milliseconds) between starting the child processes when running in parallel mode.

Selenium settings

Below are a number of options for the selenium server process. Nightwatch can start and stop the Selenium process automatically which is very convenient as you don't have to manage this yourself and focus only on the tests.

If you'd like to enable this, set start_process to true and specify the location of the jar file inside server_path.

Name type default description
start_process boolean false Whether or not to manage the selenium process automatically.
start_session
since v0.6.1
boolean true Whether or not to automatically start the Selenium session.
server_path string none The location of the selenium jar file. This needs to be specified if start_process is enabled.
E.g.: lib/selenium-server-standalone-2.43.0.jar
log_path string|boolean none The location where the selenium output.log file will be placed. Defaults to current directory.
To disable Selenium logging, set this to false
host string 127.0.0.1 Usually not required and only used if start_process is true. Specify the IP address you wish Selenium to listen on.
port integer 4444 The port number Selenium will listen on.
cli_args
since v0.5.1
object none List of cli arguments to be passed to the Selenium process. Here you can set various options for browser drivers, such as:

  • webdriver.firefox.profile: Selenium will be default create a new Firefox profile for each session. If you wish to use an existing Firefox profile you can specify its name here.
    Complete list of Firefox Driver arguments available here.
  • webdriver.chrome.driver: Nightwatch can run the tests using Chrome browser also. To enable this you have to download the ChromeDriver binary and specify it's location here. Also don't forget to specify chrome as the browser name in the desiredCapabilities object.
    More information can be found on the ChromeDriver website.
  • webdriver.ie.driver: Nightwatch has support for Internet Explorer also. To enable this you have to download the IE Driver binary and specify it's location here. Also don't forget to specify "internet explorer" as the browser name in the desiredCapabilities object.

Test settings

Below are a number of options that will be passed to the Nightwatch instance. You can specify multiple groups of options so you could have different values per environment:

{
  ...
  "test_settings" : {
    "default" : {
      ...
    },
    "integration" : {
      ...
    }
  }
}

A "default" environment is required. All the other environments are derived from default and their settings can be overridden as needed.

The key of the settings group can be passed then to the runner as the --env argument to use the specified settings, like so:

$ nightwatch --env integration

This can be useful if you need to have different settings for your local machine and the Continuous Integration server.

Name type default description
launch_url string none A url which can be used later in the tests as the main url to load. Can be useful if your tests will run on different environments, each one with a different url.
selenium_host string localhost The hostname/IP on which the selenium server is accepting connections.
selenium_port integer 4444 The port number on which the selenium server is accepting connections.
silent boolean true Whether to show extended Selenium command logs.
output boolean true Use to disable terminal output completely.
disable_colors
since v0.4.13
boolean false Use to disable colored output in the terminal.
firefox_profile
deprecated
string|boolean none This options has been deprecated in favor of the cli_args object on the selenium settings object.
chrome_driver
deprecated
string none This options has been deprecated in favor of the cli_args object on the selenium settings object.
ie_driver
deprecated
string none This options has been deprecated in favor of the cli_args object on the selenium settings object.
screenshots object none Selenium generates screenshots when command errors occur. These can be saved somewhere on the disk.
Example: "screenshots" : {"enabled" : true, "path" : ""}
username string none In case the selenium server requires credentials this username will be used to compute the Authorization header.

The value can be also an environment variable, in which case it will look like this:
"username" : "${SAUCE_USERNAME}"
access_key string none This field will be used together with username to compute the Authorization header.

Like username, the value can be also an environment variable:
"access_key" : "${SAUCE_ACCESS_KEY}"
desiredCapabilities object An object wich will be passed to the Selenium WebDriver when a new session will be created. You can specify browser name for instance along with other capabilities.
Example:

"desiredCapabilities" : {
  "browserName" : "firefox",
  "acceptSslCerts" : true
}

You can view the complete list of capabilities here.
globals
since v0.4.8
object An object wich will be made available within the test and can be overwritten per environment. Example:

"globals" : {
  "myGlobal" : "some_global"
}
exclude
since v0.4.9
array An array of folders or file patterns to be skipped (relative to the main source folder).
Example:

"exclude" : ["excluded-folder"]
or:
"exclude" : ["test-folder/*-smoke.js"]
filter
since v0.5.1
string Folder or file pattern to be used when loading the tests. Files that don't match this patter will be ignored.
Example:

"filter" : "tests/*-smoke.js"
use_xpath
since v0.5.1
boolean false Use xpath as the default locator strategy
cli_args
since v0.6.1
object none Same as Selenium settings cli_args. You can override the global cli_args on a per-environment basis.

Writing Tests

Using the preferred CSS selector model to locate elements on a page, Nightwatch makes it very easy to write automated End-to-End tests.

Create a separate folder for tests in your project, e.g.: tests. Each file inside it will be loaded as a test by the Nightwatch test runner. A basic test will look like this:


module.exports = {
  'Demo test Google' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('button[name=btnG]', 1000)
      .click('button[name=btnG]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};

Remember always to call the .end() method when you want to close your test, in order for the selenium session to be properly closed.

A test can have multiple steps, if needed:

module.exports = {
  'step one' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('button[name=btnG]', 1000)
  },

  'step two' : function (browser) {
    browser
      .click('button[name=btnG]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};

Tests can also be written in this format:


this.demoTestGoogle = function (browser) {
  browser
    .url('http://www.google.com')
    .waitForElementVisible('body', 1000)
    .setValue('input[type=text]', 'nightwatch')
    .waitForElementVisible('button[name=btnG]', 1000)
    .click('button[name=btnG]')
    .pause(1000)
    .assert.containsText('#main', 'The Night Watch')
    .end();
};

Using XPath selectors

Nightwatch supports xpath selectors also. To switch to xpath instead of css selectors as the locate strategy, in your test call the method useXpath(), as seen in the example below. To switch back to CSS, call useCss().

To always use xpath by default set the property "use_xpath": true in your test settings.


this.demoTestGoogle = function (browser) {
  browser
    .useXpath() // every selector now must be xpath
    .click("//tr[@data-recordid]/span[text()='Search Text']")
    .useCss() // we're back to CSS now
    .setValue('input[type=text]', 'nightwatch')
};

Using Page Objects

The Page Objects methodology is a popular pattern to write end-to-end tests by wrapping the pages or page fragments of a web app into objects. The purpose of a page object is to allow a software client to do anything and see anything that a human can by abstracting away the underlying html actions needed to access and manipulate the page.

A Simple Page Object

The page object is simply a class which receives the nightwatch object as an argument in the constructor. Each page object needs to be located in a separate file, located into a designated folder. Nightwatch reads the page objects from the folder specified in the page_objects_path configuration property.

The page_objects_path property can also be an array of folders, allowing you thus to logically split the page objects into smaller groups.


module.exports = function (browser) {
  // Each action is written as a separate method which must return the browser
  // object in order to be able to be queued
  this.goToGoogle = function() {
    browser
      .url('http://google.com')
      .waitForElementVisible('body', 1000);

    return browser;
  };
};

Usage

Say you have the simple page object defined above saved as a GooglePage.js file. In your tests you will use it as follows:


module.exports = {
  'Test': function (client) {
    client
      .page.GooglePage().goToGoogle()
      .assert.title('Google')
      .end();
  }
};

Further reading

A comprehensive introduction to Page Objects can be found in this article.

Using before[Each] and after[Each] hooks

Nightwatch provides the standard before/after and beforeEach/afterEach hooks to be used in the tests.

The before and after will run before and after the execution of the test suite respectively, while beforeEach and afterEach are ran before and after each testcase (test step).

All methods have the Nightwatch instance passed as argument.

Example:


module.exports = {
  before : function(browser) {
    console.log('Setting up...');
  },

  after : function(browser) {
    console.log('Closing down...');
  },

  beforeEach : function(browser) {

  },

  afterEach : function(browser) {

  },

  "step one" : function (browser) {
    browser
     // ...
  },

  "step two" : function (browser) {
    browser
    // ...
      .end();
  }
};

In the example above the sequence of method calls will be as follows: before(), beforeEach(), "step one", afterEach(), beforeEach(), "step two", afterEach(), after()

Asynchronous before[Each] and after[Each]

All the before[Each] and after[Each] methods can also perform asynchronous operations, in which case they will require the callback passed as the second argument.

The done function must be called as the last step when the async operation completes. Not calling it will hang the test runner.

Example with beforeEach & afterEach:


module.exports = {
  beforeEach: function(browser, done) {
    // performing an async operation
    setTimeout(function() {
      // finished async duties
      done();
    }, 100);
  },

  afterEach: function(browser, done) {
    // performing an async operation
    setTimeout(function() {
      // finished async duties
      done();
    }, 200);
  }
};

External Globals

In addition to having globals defined in your nightwatch.json, sometimes it's useful to have also an external globals file, specified in the globals_path property.

You can overwrite globals per environment as needed. Say you have your tests running locally and also against a remote cloud selenium server. Most of the times you will need some different setting up.

Example:


module.exports = {
  'local-env' : {
    isLocal : true,
  },

  'remote-env' : {
    isLocal : false
  },

  before: function(done) {
    // run this only for the local-env
    if (this.isLocal) {
      // start the local server
      App.startServer(function() {
        // server listening
        done();
      });
    } else {
      done();
    }
  },

  after: function(done) {
    // run this only for the local-env
    if (this.isLocal) {
      // start the local server
      App.stopServer(function() {
        // shutting down
        done();
      });
    } else {
      done();
    }
  }
};

You can refer to the provided globalsModule.js for an example.

Test Runner

Nightwatch includes a command-line test runner which makes it easy to run tests and generate useful output.

Example usage:

$ ./nightwatch --test tests/demotest.js

If you have installed nightwatch with-g (global) option you can skip this.

To use the test runner in your project simply create a new file called nightwatch and add the following:

For Linux and MacOSX:
#!/usr/bin/env node
require('nightwatch/bin/runner.js');

Then set the permissions:

$ chmod a+x nightwatch
For Windows:

Name the file nightwatch.js and add the following line:

require('nightwatch/bin/runner.js');

Then run as follows:

C:\workspace\project> node nightwatch.js

Command-line Options

The test runner supports a number of run-time options to be passed at. To view all, run the following:

$ ./nightwatch --help
Name Shortname default description
--config -c ./nightwatch.json The location of the nightwatch.json file - the configuration file which the runner uses and which also includes the Selenium WebDriver options.
--output -o tests_output The location where the JUnit XML reports will be saved.
--reporter -r junit Name of a predefined reporter (e.g. junit) or path to a custom reporter file to use.
--env -e default Which testing environment to use - defined in nightwatch.json
--verbose -v Shows extended selenium command logging during the session
--test -t Runs only the specified test. By default it will attempt to run all tests in the folder and its subfolders.
--testcase Used only together with --test. Runs the specified testcase from the current suite/module.
--group -g Runs only the specified group of tests (subfolder). Tests are grouped by being placed in the same subfolder.
--skipgroup -s Skip one or several (comma separated) group of tests.
--filter -f Specify a filter (glob expression) as the file name format to use when loading the test files.
--tags -a Filter test modules by tags. Only tests that have the specified tags will be loaded.

Test Groups

Nightwatch makes it possible to organize your test scripts into groups and run them as needed. To group tests together just place them in the same sub-folder. The folder name is the name of the group.

Example:

lib/
  ├── selenium-server-standalone.jar
custom-commands/
  ├── loginUser.js
  ├── attachPicture.js
tests/
  ├── logingroup
  |   ├── login_test.js
  |   └── otherlogin_test.js
  ├── addressbook
  |   ├── addressbook_test.js
  |   └── contact_test.js
  ├── chat
  |   ├── chatwindow_test.js
  |   ├── chatmessage_test.js
  |   └── otherchat_test.js
  └── smoketests
      ├── smoke_test.js
      └── othersmoke_test.js

To run only the smoketests group you would do the following:

$ nightwatch --group smoketests

Also, if you would want to skip running the smoketests group you would do the following:

$ nightwatch --skipgroup smoketests

To skip multiple groups, just add them as comma-separated:

$ nightwatch --skipgroup addressbook,chat

Test Tags

You can also selectively target tests to run based on tags, such that a test may be belong to multiple tags. For example, you might have a login test that belongs to a login suite as well as a sanity suite.

The tagging can be accomplished by adding thetags property to a test module:


module.exports = {
  tags: ['login', 'sanity'],
  'demo login test': function (client) {
     // test code
  }
};

To select which tags to run, use the --tag command line flag:

$ nightwatch --tag login

Specify multiple tags as:

$ nightwatch --tag login --tag something_else

Parallel Running

Starting with v0.5 Nightwatch supports the tests to be run in parallel. This works by specifying multiple environments in the command line, separated by comma. E.g.:

$ nightwatch -e default,chrome

The above will run two environments named default and chrome in parallel.

Terminal Output

Each environment will be run as a separate child_process and the output will be sent to the main process.

To make the output easier to read, Nightwatch by default buffers the output from each child process and displays everything at the end, grouped by environment.

If you'd like to disable the output buffering and see the output from each child process as it is sent to stdout, simply set the property "live_output" : true on the top level in your nightwatch.json (e.g. after selenium).
You can create a separate environment per browser (by chaining desiredCapabilities) and then run them in parallel. In addition, using the filter and exclude options tests can be split per environment in order to be ran in parallel.

Using Grunt

Grunt is a popular JavaScript task runner. Starting with version 0.6 Nightwatch is bundled with an easy to use Grunt task which can be used in your existing Grunt-based build configuration for running the tests.

Usage

First, load the Nightwatch grunt task at the top in your Gruntfile.js.


module.exports = function(grunt) {
  var nightwatch = require('nightwatch');
  nightwatch.initGrunt(grunt);

  // ...

};

Task Configuration and Targets

The Nightwatch task will have one more more targets which can be used in various ways, one way being to map them to environments. Available settings are:

  • options - the only available option so far is cwd - current working directory
  • argv - command-line arguments that would normally be passed to the Nightwatch runner (e.g.: env);
  • settings - the test settings specified to a single Nightwatch environment.

Example


grunt.initConfig({
  nightwatch: {
    options: {
      cwd: './'
    },

    'default' : {},

    browserstack: {
      argv: {
        env: 'browserstack'
      },
      settings: {
        silent: true
      }
    },

    'all' : {
      argv: {
        env: 'default,browserstack'
      }
    },
  }
});


Run the task as follows:

$ grunt nightwatch:default
or
$ grunt nightwatch:browserstack


There are also a few third-party Grunt plugins for Nightwatch which can be used instead, if you prefer. The most popular one is grunt-nightwatch.

Writing Custom Commands

Most of the time you will need to extend the Nightwatch commands to suit your own application needs. Doing that is only a matter of creating a separate folder and defining your commands in that folder, each one inside its own file.

Then specify the path to that folder inside the nightwatch.json file, as the custom_commands_path property. The command name is the name of the file itself, and it needs to follow the following pattern:


exports.command = function(file, callback) {
  var self = this, imageData, fs = require('fs');

  try {
    var originalData = fs.readFileSync(file);
    var base64Image = new Buffer(originalData, 'binary')
      .toString('base64');
    imageData = 'data:image/jpeg;base64,' + base64Image;
  } catch (err) {
    console.log(err);
    throw "Unable to open file: " + file;
  }

  this.execute(
    function(data) { // execute application specific code
      App.resizePicture(data);
      return true;
    },

    [imageData], // arguments array to be passed

    function(result) {
      if (typeof callback === "function") {
        callback.call(self, result);
      }
    }
  );

  return this; // allows the command to be chained.
};

The example below defines a command (e.g. resizePicture.js) which loads an image file as data-URI and calls a method named resizePicture defined inside the application.

With this command, the test will look something like:


module.exports = {
  "testing resize picture" : function (browser) {
    browser
      .url("http://app.host")
      .waitForElementVisible("body")
      .resizePicture("/var/www/pics/moon.jpg")
      .assert.element(".container .picture-large")
      .end();
  }
};

Writing Custom Assertions

Nightwatch allows you to even define your own assertions, extending the available .assert and .verify namespaces.

Beginning with v0.4 assertions have a very simple interface which is shared between built-in assertions and custom ones. Therefore, custom assertions must implement the following interface:


exports.assertion = function() {

  /**
   * The message which will be used in the test output and
   * inside the XML reports
   * @type {string}
   */
  this.message;

  /**
   * A value to perform the assertion on. If a function is
   * defined, its result will be used.
   * @type {function|*}
   */
  this.expected;

  /**
   * The method which performs the actual assertion. It is
   * called with the result of the value method as the argument.
   * @type {function}
   */
  this.pass = function(value) {

  };

  /**
   * The method which returns the value to be used on the
   * assertion. It is called with the result of the command's
   * callback as argument.
   * @type {function}
   */
  this.value = function(result) {

  };

  /**
   * Performs a protocol command/action and its result is
   * passed to the value method via the callback argument.
   * @type {function}
   */
  this.command = function(callback) {

    return this;
  };

};

Both custom assertions and custom commands inherit from EventEmitter if defined in the form above.
If, however, your command/assertion is defined in the constructor style, then you must inherit manually, similarly to the pause command.

To see some examples, check the assertions module source-code on Github:
/nightwatch/tree/master/lib/selenium/assertions

Custom Reporter

If you'd like to define your own reporter in addition to the built-in ones (stdout and junit-xml) you can do so in two ways:

The --reporter command-line argument

Interface:


module.exports = {
  write : function(results, options, done) {
    done();
  }
};

The reporter method in your external globals file.

See the provided globalsModule.js for an example.

Example:


module.exports = {
  reporter : function(results, done) {
    console.log(results);
    done();
  }
};

Writing Unit Tests

Since version 0.6 it's possible to also write unit or integration tests in Nightwatch for Node.js applications and APIs. This concept is still very new to Nightwatch so bear in mind this feature is not yet as stable or as feature-rich as a mature unit testing framework.

Disabling automatic selenium session

Nightwatch automatically attempts to connect to the specified selenium server and create a session. When running unit tests this needs to be disabled by setting the start_session property to false inside the selenium settings group either on the root level or inside a specific environment.

Assertion framework

The client object bundles the Node.js Assert module, same way as for end-to-end testing. Custom commands and assertions are also loaded and made available, together with globals.

Example

Below there's a unit test for the utils.js Nightwatch module:


var Utils = require('ib/util/utils.js');
module.exports = {
  testFormatElapsedTime : function(client) {
    var test = client.assert;

    var resultMs = Utils.formatElapsedTime(999);
    var resultSec = Utils.formatElapsedTime(1999);
    var resultMin = Utils.formatElapsedTime(122299, true);

    test.equal(resultMs, '999ms');
    test.equal(resultSec, '1.999s');
    test.equal(resultMin, '2m 2s / 122299ms');
  },

  testMakeFnAsync : function(client) {
    function asynFn(done) {
      done();
    }

    function syncFn() {}

    var test = client.assert;

    test.equal(Utils.makeFnAsync(1, asynFn), asynFn);

    var convertedFn = Utils.makeFnAsync(1, syncFn);
    convertedFn(function() {
      test.ok('converted fn called');
    });
  }
};

Asynchronous Unit Tests

The second argument to a test function, if provided, is the done callback which signals the test is complete. If present, the callback must be called when the async operation finishes.

Example

Below there's a unit test for the utils.js Nightwatch module:


module.exports = {
  'demo UnitTest' : function (client, done) {
    client.assert.ok('TEST');

    setTimeout(function() {
      done();
    }, 500);
  }
};

Using Third-party Assertion Frameworks

It's also possible to use a third-party assertion framework for writing tests. The example below uses Chai.


var Utils = require('lib/util/utils.js');
var expect = require('chai').expect;

module.exports = {
  testFormatElapsedTime : function(client) {
    var resultMs = Utils.formatElapsedTime(999);
    var resultSec = Utils.formatElapsedTime(1999);
    var resultMin = Utils.formatElapsedTime(122299, true);

    expect(resultMs).to.equal('999ms');
    expect(resultSec).to.equal('1.999s');
    expect(resultMin).to.equal('2m 2s / 122299ms');
  }
};

Using a Combined Configuration

Below it's an example of how you can combine end-to-end tests and unit tests in the same nightwatch.json configuration file. Notice the usage of exclude and filter properties.

An empty exclude means we want to reset its value and rely only on filter.

{
  "src_folders" : ["./examples/tests", "./examples/unittests"],
  "output_folder" : "./examples/reports",

  "selenium" : {
    "start_process" : true,
    "server_path" : "./bin/selenium-server-standalone.jar",
    "log_path" : "",
    "host" : "127.0.0.1",
    "port" : 4444,
    "cli_args" : {
      "webdriver.chrome.driver" : "",
      "webdriver.ie.driver" : ""
    }
  },

  "test_settings" : {
    "default" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4444,
      "selenium_host"  : "localhost",
      "silent": true,
      "screenshots" : {
        "enabled" : false,
        "path" : ""
      },
      "desiredCapabilities": {
        "browserName": "firefox",
        "javascriptEnabled": true,
        "acceptSslCerts": true
      },
      "exclude" : "./examples/unittests/*"
    },

    "unittests" : {
      "selenium" : {
        "start_process" : false,
        "start_session" : false
      },
      "filter" : "./examples/unittests/*",
      "exclude" : ""
    }
  }
}