Jan 28, 2022

The public NPM release of Nightwatch 2.0 is here and can be installed directly with:

npm i nightwatch --save-dev

Over the past few weeks we have worked tirelessly to finalise the apis, add a few more examples, and try and smooth over any rough edges.

Important Changes

  • Added a new plugin API; check out the docs for how to create a Nightwatch plugin: nightwatchjs.org/guide/extending-nightwatch/plugin-api.html
  • Added support for using nightwatch.conf.cjs as config file for projects that use ES Modules
  • Upgraded chai expect to version 5 and added support for using regular chai browser.expect() assertions; this doesn't affect the existing expect.element(), expect.elements(), expect.cookie(), expect.title(), and expect.url().
    • Example:
      const infoElement = element('.info');
      .and.to.include('validation code');
      See examples/tests/shadowRootExample.js for the complete example.


  • Added several new assertions:
    • titleEquals
    • titleMatches
    • urlMatches
    • textMatches
    • textEquals
    • domPropertyMatches
    • attributeMatches
    • valueEquals
    • hasClass
    • hasAttribute
    • elementsCount
  • Added new element commands:
    • getFirstElementChild
    • getNextSibling
    • getPreviousSibling
    • hasDescendants
    • isPresent
  • Added new API mouse actions:
    • clickAndHold
    • rightClick
    • releaseMouseButton
  • Added new --devtools CLI flag to open the Chrome Devtools automatically


  • Fixed #2955 - an issue caused by missing the browserName capability
  • Fixed fixed an issue with creating the log folder for writing the webdriver logs (2cff6df2d06f02ef2ed853c89795d3210d2a35c0)


Jan 19, 2022

  • Added more supporting CucumberJS cli options (#2978)
  • Fixed a compatibility issue caused by Selenium (#2999)


Dec 15, 2021

  • Fixed Fixed a regression issue with using execute() command - #2970
  • Updated selenium-webdriver to v4.1 and other depedencies


Nov 4, 2021

We're delighted to present the first beta version of Nightwatch v2.0! Upcoming beta releases will incrementally be made available in NPM under the next tag, so in order to install it you'll have to run the following:

npm i nightwatch@next

Over the coming weeks we will also finish updating the documentation website with more pages in the Guide section and documenting the new APIs.

Important Changes

Since the previous alpha release we have only added a few improvements and several fixes. The fixes are mainly concerning working with the new element() api and using cucumber-js.


  • Added dragAndDrop element command which uses the new Actions API from Selenium – #2920;
  • Added support to use the config file as Promise – #2896
  • Added support to use glob patterns in config for src_folders, page_object_path, custom_commands_path, custom_assertion_path options – #2910;
  • Added new webdriver.log_file_name setting to specify the filename where webdriver server logs should be written – 127760130341328010b9001598812916ace92363
  • Added support to write individual webdriver server logs for each test suite – 127760130341328010b9001598812916ace92363
  • Added support to define page object commands as an ES6 class – example db03e68032c07c2c1321cf8e278016fb0c742c87;
  • Added support to use Selenium WebElement ids as arguments to element commands, such as .click(), e.g.: ```js // with async const elements = await browser.findElements('input'); await browser.click(elements[1]);

// with callback browser.findElements('input', function(result) { browser.click(result.value[1]); });

### Fixes
- Reverted `getAttribute` command to use the [W3C endpoint](https://w3c.github.io/webdriver/#get-element-attribute) instead of the Selenium atom script - #2926; 
- Fixed an issue where the session was hanging after a failure when using `suiteRetries` – 127760130341328010b9001598812916ace92363

## Examples
We've also updated the bundled [**examples**](https://github.com/nightwatchjs/nightwatch/tree/v2/examples) so do make sure to check those out in order to get a better feel about the new Nightwatch 2 features.

#### Search for the term "Nightwatch.js" using:
- Google: [examples/tests/google.js](https://github.com/nightwatchjs/nightwatch/blob/v2/examples/tests/google.js)
- DuckDuckGo: [examples/tests/duckDuckGo.js](https://github.com/nightwatchjs/nightwatch/blob/v2/examples/tests/duckDuckGo.js)
- Ecosia.org: [examples/tests/ecosia.js](https://github.com/nightwatchjs/nightwatch/blob/v2/examples/tests/ecosia.js)

#### Google search using page objects
- [examples/tests/googlePageObject.js](https://github.com/nightwatchjs/nightwatch/blob/v2/examples/tests/googlePageObject.js)

#### ToDo App on AngularJs homepage
- [examples/tests/angularTest.js](https://github.com/nightwatchjs/nightwatch/blob/v2/examples/tests/angularTest.js)
- this contains demo on how to use the new `element()` global api

You can run any of the examples by simply referring to the examples folder like below:
npx nightwatch examples/tests/angularTest.js

CucumberJS examples

The bundled config file which is auto-generated by Nightwatch on the first run (only if one is not already present in the project), contains configuration and examples for running the CucumberJS examples immediately, using the following:

npx nightwatch --env cucumber-js


Oct 17, 2021

New features

  • Added enable_fail_fast setting and --fail-fast cli argument to abort the test runner after a failed test suite

Important Changes

Below are notable changes from the previous alpha version (2.0.0-alpha.3):

  • Updated the integrated Cucumber test runner - see working with cucumber in Nightwatch for details;
  • Updated the new creatClient() external method for programmatic usage; the new client now contains the following methods:
    • client.settings - returns the current settings
    • client.updateCapabilities() - can be used to updated capabilities before starting a new Webdriver session (before calling .launchBrowser())
    • client.launchBrowser()
const Nightwatch = require('nightwatch');

const client = Nightwatch.createClient({
  browserName: 'firefox',
  headless: true

  testCapability: 'one, two, three'
const browser = await client.launchBrowser();

Other Changes:

  • Improved terminal output in case of session create errors
  • Removed deprecated request dependency
  • Fixed an issue with making the browser object available as a global
  • Updated Mocha to v9.1.3 and added support for the mocha runner to use the disable_colors setting


Oct 11, 2021

Nightwatch v2.0.0-alpha.3

New features

  • Added integrated test runner for Cucumber - more info on config and usage available in examples folder
  • Added new 'createClient()' programatic api exported on the main library; usage:
const Nightwatch = require('nightwatch');

const client = Nightwatch.createClient({
  headless: true,
  output: true,
  silent: true, // set to false to enable verbose logging
  browserName: 'firefox', // can be either: firefox, chrome, safari, or edge
  timeout: 10000, // set the global timeout to be used with waitFor commands and when retrying assertions/expects
  env: null, // set the current test environment from the nightwatch config
  desiredCapabilities: {
    // any additional capabilities needed
  globals: {}, // can define/overwrite test globals here; when using a third-party test runner only the global hooks onBrowserNavigate/onBrowserQuit are supported
  parallel: false, // when the test runner used supports running tests in parallel; set to true if you need the webdriver port to be randomly generated
  // All other settings can be overwritten here, such as:
  disable_colors: false

const browser = await client.session();


  • Updated the bundled Mocha test runner to use Mocha v9 and added other features supported by the default nightwatch test runner (such as using test tags, global hooks etc.); pending Mocha v9.1.3 which contains https://github.com/mochajs/mocha/issues/4760

  • New API commands:

    • browser.navigateTo(url, [callback]) - navigates to a new url. Accepts also relative urls if launchUrl is defined in the config and will execute onBrowserNavigate global hook after the url is loaded.

    • browser.getCurrentUrl([callback])

    • browser.quit([callback]) - ends the session and closes down the test WebDriver server, if one is running. This is similar to calling the .end() command, but the former doesn't quit the WebDriver session. It also executes the onBrowserQuit global hook before ending the session.

    • browser.setAttribute([using], selector, property, [callback]) - set the value of a specified DOM attribute for the given element.


  • Fixed an issue with using moveToElement and moveTo api commands
  • Fixed isVisible() command to use the proper action from selenium-webdriver
  • Fixed an issue where the sink process used by the Webdriver child process was causing the runner to stop working on Windows
  • Renamed global object "Key" to "Keys"


Sep 17, 2021

  • This version is only updating the proxy-agent dependency package to the latest version.

Sep 15, 2021

  • Fixed #2899 – an issue with setValue/sendKeys commands
  • Added new updateValue command


Sep 12, 2021

  • Fixed an issue where selenium_host config property wasn't set (#2892 )
  • Added support to set browserName to null in order to accommodate Appium (#2882)


Sep 7, 2021

Nightwatch v2.0-alpha

The next major version of Nightwatch is finally available in NPM as an alpha pre-release. It contains a wide range of new features and improvements for writing and running tests as well as full cross-browser testing support for W3C WebDriver compliant browsers.

The underlying architecture was completely reworked to use the official selenium-webdriver library in communicating with the browser drivers. This means better cross-browser integration, more reliable DOM element command handling, and overall more stable and faster tests. It also means that the newest features and capabilities of WebDriver will be directly available in Nightwatch, such as the upcoming Webdriver BiDi protocol, deemed as "the future of cross-browser automation".

To install, run:

npm i nightwatch@alpha

New features

Support for the WebDriver Actions API

WebDriver provides a comprehensive API for generating complex user gestures called the Actions API. This is available and ready to use in Nightwatch via the existing .perform() command. The previous functionality of the perform() command is still there and working in the same way as before.

Here's a basic example on how to use the new actions api:

try {
  const performResult = await browser.perform(function() {
    const actions = this.actions({async: true});

    return actions

  console.log('perform', performResult)
} catch (err) {

More examples in the selenium api docs. In the example above, the Actions class instance is created using this.actions(<options>). The .perform() at the end (which is needed in the selenium docs) should be omitted in Nightwatch, as it will be called automatically.

Support for Chrome DevTools protocol

Both ChromeDriver and EdgeDriver expose some specific commands for working with their respective browsers.

When using ChromeDriver or EdgeDriver it is now possible to execute commands via the Chrome DevTools protocol. Here's the full list of commands available on the chrome namespace on the Nightwatch browser object:

More info:

Support for Firefox specific commands

The FirefoxDriver exposes some specific commands, such as for setting context to run "privileged" javascript code or for working with addons. These are now available on in Nightwatch directly, on the firefox namespace.

More info:

New .ensure assertions

The new .ensure namespace is based on the until module from selenium-webdriver.


describe('demo test for .ensure', function() {
  test('basic test', function(browser) {

New element() global and support for using WebElements

The newly added element() global can be used to pre-construct element objects outside of test cases. It is also possible to use the newly added by() global utility which is equivalent to using the By() class from selenium-webdriver to create element locators.

In addition, the browser object is also available as global, so it's not necessary to pass it as an argument to tests, as it is the case in Nightwatch v1.x.

It is also possible to disable the global apis by setting disable_global_apis to true in your nightwatch config file.


const assert = require('assert');
const {WebElement} = require('selenium-webdriver');

describe('demo element() global', function() {
  const signupEl = element(by.css('#signupSection'));
  const loginEl = element('#weblogin');

  test('element globals command',  async function() {
    const tagName = await browser.waitForElementPresent(loginEl, 100).getTagName(loginEl);
    assert.strictEqual(tagName, 'div');

    // use elements created with element() to regular nightwatch assertions

    // use elements created with element() to expect assertions

    // retrieve the WebElement instance
    const loginWebElement = await loginEl.getWebElement();
    assert.ok(loginWebElement instanceof WebElement);

Using the Selenium WebDriver object directly

The WebDriver instance is available as well on the Nightwatch api object as the driver property.

If you wish to chain WebDriver specific commands, you'll need to wrap them inside either a perform() or a waitUntil() command.


describe('demo driver object', function() {

  it('get browser logs – classic',  function() {
      .perform(function() {
        this.driver.manage().logs().get('browser').then(result => {
          console.log('Browser logs:', result)

  it('get browser logs – with ES6 async/await', async function() {
    await browser.url('https://nightwatchjs.org').waitForElementVisible('body');
    const logs = await browser.driver.manage().logs().get('browser');

    console.log('Browser logs:', logs)

Using WebDriver BiDi in Nightwatch

The WebDriver BiDi is the new protocol for communicating with browsers, defined as a new W3C spec, currently in progress.

Early support is available in Selenium 4 and it is already available in ChromeDriver via the Chrome Developer Tools.

WebDriver Bidi allows users to capture events from the browser as they happen rather than using the traditional approach of request/response that WebDriver is using for other APIs.

Internally WebDriver will create a WebSocket connection to the browser for events and commands to be transmitted.


The below example calls the Page.getLayoutMetrics method from CDP via a WebDriver Bidirectional connection over a WebSocket.

describe('demo webdriver bidirectional', function() {

  it('samepl test bidi', async function(browser) {
    await browser.url('http://nightwatchjs.org/');

    const cdpConnection = await browser.driver.createCDPConnection('page');
    browser.assert.ok(cdpConnection._wsConnection && cdpConnection._wsConnection._url.startsWith('ws://'),
            `CDP connection is successful to: ${cdpConnection._wsConnection._url}`);

    const layoutMetrics = await browser.perform(function(callback) {
      const id = 99;
      cdpConnection._wsConnection.on('message', function getLayoutMetrics(message) {
        const params = JSON.parse(message)
        if (params.id === 99) {
          cdpConnection._wsConnection.off('message', getLayoutMetrics);

      cdpConnection.execute('Page.getLayoutMetrics', id, {});

    console.log('Layout Metrics:', layoutMetrics)

New API commands

A few new commands have been added and also compatibility has been improved for several existing commands.

  • browser.getAccessibleName(<selector> | <WebElement>)

    returns the computed WAI-ARIA label of an element.

     const result = await browser.getAccessibleName('input[type=search]');
  • browser.getAriaRole(<selector> | <WebElement>)

    returns the computed WAI-ARIA role of an element.

     const result = await browser.getAriaRole('input[type=search]');
  • browser.takeElementScreenshot(<selector> | <WebElement>)

    take a screenshot of the visible region encompassed by an element's bounding rectangle.

     const data = await browser.takeElementScreenshot('#container');
     require('fs').writeFile('out.png', data, 'base64');
  • browser.uploadFile(<selector> | <WebElement>)

    uploads file to an element using absolute file path.

     await browser.uploadFile('#myFile', '/path/to/file.pdf');
  • browser.waitUntil(<conditionFunction>, [optionalMaxTimeout], [optionalRetryInterval], [optionalCallback])

    a generic command which can make the test runner wait for a condition to evaluate to a "truthy" value. The condition may be specified by any function which returns the value to be evaluated or a Promise to wait for. If the condition is not satisfied, a TimeoutError will be thrown and the test will fail.

     let conditionValue;
     await browser.waitUntil(function() {
        return conditionValue === true;
     await browser.waitUntil(async function() {
       const title = await this.execute(function() {
          return document.title;
       return title === 'Nightwatch.js';
     }, 1000);


Using async/await

We have changed the result format of Nightwatch commands to return the value directly when using the await operator.

The value passed to callback remains the same as in v1.x. This behaviour can be disabled by setting the backwards_compatibility_mode to true in your nightwatch config.


Getting the value when using await:

const value = await browser.getText('#weblogin');
console.log('Value is:', value);

Getting the value when using a callback:

browser.getText('#weblogin', function(result) {
  console.log('Value is:', result.value);  

Defining WebDriver capabilities

It is now possible to define session capabilities by setting an instance of a Selenium Capabilities object in your nightwatch.conf.js file as the capabilities value.

You can refer to the Selenium documentation for all the available capabilities. Here's an example for defining a capabilities object in your nightwatch.conf.js for Chrome in headless mode:


// nightwatch.conf.js
const chrome = require('selenium-webdriver/chrome');
const capabilities = new chrome.Options();

module.exports = {
  test_settings: {
    chrome: {
      webdriver: {
        start_process: true,
        server_path: require('chromedriver').path,
        cli_args: [
          // --verbose

Using try/catch

When writing an async testcase, it is now possible to catch errors locally and prevent them from bubbling up to the global error handler.

This can be used in implementing custom error handling or in more advanced scenarios. You can catch locally errors thrown from generic commands like .perform() or .waitUntil().

In the case of Nightwatch assertions, you can also catch the failed assertion error but the testcase will still fail. Catching the error is the equivalent of setting abortOnFailure flag to false (or abortOnAssertionFailure if set globally). The purpose is to continue running the rest of the testcase, even after a failed assertion.


describe('demo async testcase with try/catch', function() {

  test('sample test',  async function() {
    try {
      const result = await browser.perform(function() {
        throw new Error('Error from perform');
    } catch (err) {
      // The error throw in the perform() command is caught here
      console.error('Error:', err);

    try {
      await browser.assert.visible('.wrong_selector');
    } catch (err) {
      // The assertion error is caught but the testcase will still fail at the end
      console.log('Assertion Error:', err)

New config settings

Below are new settings introduced in v2.0 and their default values:

  // Set this to true to use the v1.x response format for commands when using ES6 async/await 
  backwards_compatibility_mode: false,

  // Set this to true to disable the global objects such as element(), browser, by(), expect()          
  disable_global_apis: false,

  // Ignore network errors (e.g. ECONNRESET errors)
  report_network_errors: true,

  // Interactive element commands such as "click" or "setValue" can be retried if an error occurred (such as an "element not interactable" error)
  element_command_retries: 2,

  // Sets the initial window size: {height: number, width: number}          
  window_size: undefined

New WebDriver config settings

Below are new webdriver settings introduced in v2.0 for various browser drivers:

  webdriver: {
    // Sets the path to the Chrome binary to use. On Mac OS X, this path should reference the actual Chrome executable, not just the application binary (e.g. "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").
    chrome_binary: '',

    // Sets the path to Chrome's log file. This path should exist on the machine that will launch Chrome.        
    chrome_log_file: '',

    // Configures the ChromeDriver to launch Chrome on Android via adb.          
    android_chrome: false,

    // Sets the path to the Edge binary to use. 
    edge_binary: '',

    // Sets the path to the Edge binary to use.            
    edge_log_file: '',

    // Sets the binary to use. The binary may be specified as the path to a Firefox executable or a desired release Channel.            
    firefox_binary: '',

    // Sets the path to an existing profile to use as a template for new browser sessions. This profile will be copied for each new session - changes will not be applied to the profile itself.            
    firefox_profile: ''

Breaking changes

We have tried to minimize the amount of breaking changes as much as possible but some of them were difficult to avoid. Some already deprecated functionality has also been removed.

Here's a summary. Let us know on Github if something else doesn't work after upgrading from a 1.5 or higher version.

  • when using ES6 async/await test cases, the result value of Nightwatch commands does not contain the status and value properties, but simply the value (this can be reversed by setting backwards_compatibility_mode to true in your nightwatch config)
  • setValue now clears the value before sending the key strokes
  • sendKeys is no longer an alias of setValue, since it's not clearing the value but instead simply sends the keys

  • In case of element locate errors:

    • changes in the result object:
      • contains an error property which is an Error object instance
      • no longer contains httpStatusCode property
      • no longer contains value property
  • removed proxy-agent as dependency since it was frequently causing dependency issues; the proxy-agent package can be installed separately from NPM and used in the same way.


Jul 30, 2021

  • Fixed #2777 – an issue with using Chrome and Edge in parallel (#2790)
  • Fixed #2794 – using .verify asserts with await or waitFor commands with abortOnFailure=false didn't work in case of test failure (#2802, #2797)
  • Fixed #2817 – inconsistent response format when using findElements command (#2820)
  • Added support to send last error as failure reason in Browserstack transport (#2778)


Jun 29, 2021

  • Fixed #2748 - tests not running in parallel when source folder is specified as cli argument

Jun 21, 2021

  • Fixed #2755 – npm postinstall issue on windows


Jun 18, 2021

  • Fixed an issue with parallel running where the number of available workers wasn't set correctly in some cases - 7754054b34fcc750549d6a204f7f03dbaec97a41
  • Fixed xml output generation when running tests with multiple environments in parallel (#2734)


Jun 13, 2021

Nightwatch v1.7

New features

Nightwatch v1.7.0 introduces a few major new features and improvements for the test runner and also regarding the test syntax, such as:

Fluent API

It is now possible to use ES6 async/await syntax and also chain api commands together in the same test case; e.g.:

it('find elements example', async function(browser) {
    const resultElements = await browser
      .findElements('.features-container li');

    resultElements.forEach(item => console.log('Element Id:', item.getId()))

Integrated support for Microsoft Edge

You can now use the newer (Chromium-based) Microsoft Edge browser to run your Nightwatch tests. The auto-generated nightwatch.conf.js already includes configuration, so you can just run by passing the edge environment:

$ nightwatch --env edge

Parallelism for Firefox, Chrome, Safari, and Edge

You can now run tests in parallel via workers in any browser. Not only that, but now you can also run via test workers across multiple browsers in parallel.


$ nightwatch --env edge,firefox,chrome --parallel

New API commands

  • .findElement() / .findElements() - these commands provide improved support for locating single/multiple elements on the page; the response contains the web element id and a .getId() convenience method.


const resultElements = await browser.findElements('.features-container li');
resultElements.forEach(item => console.log('Element Id:', item.getId()))

const resultElement = await browser.findElement('.features-container li:first-child');
console.log('Element Id:', resultElement.getId());
  • .setPassword - support to redact params in logs (#2672)
  • .isSelected() element command and assert.selected() assertion
  • .isEnabled() element command and assert.enabled() assertion

Fixes & Improvements

  • Added support to recursively append properties from super-env in test-settings (#2718)
  • Fixed #2695 - use locate strategy from args when valid strategy is found for waitFor element commands (#2716)
  • Fixed #2677 - add option to disable loading of typescript tests
  • Fixed an issue where test status wasn't reported for parallel runs (#2733)

All releases