Overview
What is Nightwatch?
Nightwatch.js is an automated testing framework for web applications and websites, written in Node.js and using the W3C WebDriver API (formerly Selenium WebDriver).
It is a complete browser (End-to-End) testing solution which aims to simplify the process of setting up Continuous Integration and writing automated tests. Nightwatch can also be used for writing Node.js unit tests.
Nightwatch got its name from the famous painting The Night Watch by Dutch artist Rembrandt van Rijn. The masterpiece is prominently displayed in the Rijksmuseum, in Amsterdam - The Netherlands.
Overview of WebDriver
WebDriver is a general purpose library for automating web browsers. It was started as part of the Selenium project, which is a very popular and comprehensive set of tools for browser automation, initially written for Java but now with support for most programming languages.
Nightwatch uses the WebDriver API to perform the browser automation related tasks, like opening windows and clicking links for instance.
WebDriver is now a W3C specification, which aims to standardize browser automation. WebDriver is a remote control interface that enables introspection and control of user agents. It provides a platform and a restful HTTP api as a way for web browsers to be remotely controlled.
Theory of Operation
Nightwatch works by communicating over a restful HTTP api with a WebDriver server (typically the Selenium server). The restful API protocol is defined by the W3C WebDriver API. See below for an example workflow for browser initialization.

Most of the times, Nightwatch needs to send at least 2 requests to the WebDriver server in order to perform a command or assertion, 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.
Installation
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 [-g] nightwatch
Add -g option to make nightwatch runner available globally in your system.
Selenium Server Setup
The most common WebDriver implementation is the Selenium Server. This allows you to manage multiple browser configurations in one place. However, you can also run the individual browser drivers directly, such as the ChromeDriver, more details are available in the Browser Drivers Setup section.
Selenium Server
Selenium Server is a Java application which Nightwatch uses to connect to the various browsers. It runs separately on the machine with the browser you want to test. You will need to have the Java Development Kit (JDK) installed, minimum required version is 7. You can check this by running java -version from the command line.
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
Using Selenium
For viewing all the run-time options, run the previous command adding the -help:
$ java -jar selenium-server-standalone-{VERSION}.jar -help
Starting with Selenium 3, FirefoxDriver is no longer included in the package. Also, starting with version 48, Firefox is no longer compatible with FirefoxDriver which is shipped with Selenium 2.x. Firefox users are advised to use GeckoDriver for their testing. For more info, refer to the browser setup section.
More info about running the Selenium Server can be found here: https://github.com/SeleniumHQ/selenium/wiki/RemoteWebDriverServer
Configuration
The test runner expects a configuration file to be passed, using by default a nightwatch.json file from the current directory, if present. A nightwatch.conf.js file will also be loaded by default, if found.
Let's create the nightwatch.json in the project's root folder and add this inside:
{
"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" : "",
"port" : 4444,
"cli_args" : {
"webdriver.chrome.driver" : "",
"webdriver.gecko.driver" : "",
"webdriver.edge.driver" : ""
}
},
"test_settings" : {
"default" : {
"launch_url" : "http://localhost",
"selenium_port" : 4444,
"selenium_host" : "localhost",
"silent": true,
"screenshots" : {
"enabled" : false,
"path" : ""
},
"desiredCapabilities": {
"browserName": "firefox",
"marionette": true
}
},
"chrome" : {
"desiredCapabilities": {
"browserName": "chrome"
}
},
"edge" : {
"desiredCapabilities": {
"browserName": "MicrosoftEdge"
}
}
}
}
Using both configuration files is also possible, with nightwatch.conf.js always taking precedence if both are found.
Example
module.exports = (function(settings) {
settings.test_workers = false;
return settings;
})(require('./nightwatch.json'));
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 |
string|array | none | Location(s) where page object files will be loaded from. |
| globals_path Optional |
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. |
| test_workers Optional |
boolean|object | false | Whether or not to run individual test files in parallel. If set to true, runs the tests in parallel and determines the number of workers automatically. If set to an object, can specify specify the number of workers as "auto" or a number.
Example: "test_workers" : {"enabled" : true, "workers" : "auto"} |
| test_runner Optional since v0.8.0 |
string|object | "default" | Specifies which test runner to use when running the tests. Values can be either default (built in nightwatch runner) or mocha.Example: "test_runner" : {"type" : "mocha", "options" : {"ui" : "tdd"}} |
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 | boolean | true | Whether or not to automatically start the Selenium session. This will typically be set to false when running unit/integration tests that don't interact with the Selenium server. |
| server_path | string | none | The location of the selenium jar file. This needs to be specified if start_process is enabled.E.g.: bin/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 |
| port | integer | 4444 | The port number Selenium will listen on. |
| cli_args | object | none | List of cli arguments to be passed to the Selenium process. Here you can set various options for browser drivers, such as:
|
Test settings
Below are a number of settings that will be passed to the Nightwatch instance. You can define multiple sections (environments) of test settings so you could overwrite specific values per environment.
A "default" environment is required. All the other environments are inheriting from default and can overwrite settings as needed.
{
...
"test_settings" : {
"default" : {
"launch_url" : "http://localhost",
"globals" : {
"myGlobalVar" : "some value",
"otherGlobal" : "some other value"
}
},
"integration" : {
"launch_url" : "http://staging.host",
"globals" : {
"myGlobalVar" : "other value"
}
}
}
}
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.
The launch_url property
This property will be made available to the main Nightwatch api which is used in the tests. Its value depends on which environment is used.
If you run your tests as in the example above (with --env integration) launch_url will be set to http://staging.host, as per the configuration. Otherwise it will have the value defined in the default environment (i.e. http://localhost).
module.exports = {
'Demo test' : function (browser) {
browser
.url(browser.launchUrl)
// ...
.end();
}
};
Test globals
A very useful concept that Nightwatch provides is test globals. In its most simple form, this is a dictionary of name-value pairs which is defined in your nightwatch.json configuration file.
Like the launch_url property, this is made available directly on the Nightwatch api which is passed to the tests. It is also dependent on the environment used, having the ability to overwrite specific globals per environment.
If we still pass the --env integration option to the runner, then our globals object will look like below:
module.exports = {
'Demo test' : function (browser) {
console.log(browser.globals);
// {
// "myGlobalVar" : "some value",
// "otherGlobal" : "some other value"
// }
}
};
By default, a deep object copy will be created for each test suite run. If you'd like to maintain the same object throughout the entire tests run, set the persist_globals option to true, as detailed below.
Full list of settings
| 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. |
| request_timeout_options since v0.9.11 |
object | 60000 / 0 | Defines the number of milliseconds an HTTP request to the Selenium server will be kept open before a timeout is reached. After a timeout, the request can be automatically retried a specified number of times, defined by the retry_attempts property.
Example: "request_timeout_options": {
|
| silent | boolean | true | Whether to show extended Selenium command logs. |
| output | boolean | true | Use to disable terminal output completely. |
| disable_colors | 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. With on_failure set to true, also generates screenshots for failing or erroring tests. These are saved on the disk. Since v0.7.5 you can disable screenshots for command errors by setting "on_error" to false.
Example: "screenshots" : { |
| 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}"
|
| proxy since v0.8.6 |
string | none | Proxy requests to the selenium server. http, https, socks(v5), socks5, sock4, and pac are accepted. Uses node-proxy-agent. Example: http://user:pass@host:port |
| desiredCapabilities | object | An object which 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" : {You can view the complete list of capabilities here. |
|
| globals | object | An object which will be made available within the test and can be overwritten per environment. Example:"globals" : {
|
|
| exclude | 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 | string | Folder or file pattern to be used when loading the tests. Files that don't match this pattern will be ignored. Example: "filter" : "tests/*-smoke.js" |
|
| log_screenshot_data | boolean | false | Do not show the Base64 image data in the (verbose) log when taking screenshots. |
| use_xpath | boolean | false | Use xpath as the default locator strategy |
| cli_args | object | none | Same as Selenium settings cli_args. You can override the global cli_args on a per-environment basis. |
| end_session_on_fail | boolean | true | End the session automatically when the test is being terminated, usually after a failed assertion. |
| skip_testcases_on_fail | boolean | true | Skip the remaining testcases (or test steps) from the same test suite (i.e. test file), when one testcase fails. |
| output_folder since v0.8.18 |
string|boolean | Define the location where the JUnit XML report files will be saved. This will overwrite any value defined in the Basic Settings section. If you'd like to disable the reports completely inside a specific environment, set this to false. |
|
| persist_globals since v0.8.18 |
boolean | false | Set this to true if you'd like to persist the same globals object between testsuite runs or have a (deep) copy of it per each testsuite. |
| compatible_testcase_support since v0.9.0 |
boolean | false | Applies to unit tests. When set to true this allows for tests to be written in the standard Exports interface which is interchangeable with the Mocha framework. Prior unit tests interface support is deprecated and this will become the default in future releases. |
| detailed_output since v0.9.0 |
boolean | true | By default detailed assertion output is displayed while the test is running. Set this to false if you'd like to only see the test case name displayed and pass/fail status. This is especially useful when running tests in parallel. |
Browser Drivers Setup
This section contains guides for getting started with most of the major browsers and setup instructions on how to configure the individual webdriver implementations to work with Nightwatch.
The individual drivers described here are usually standalone applications which are used to interact with the browsers via the WebDriver HTTP API. You can run them either directly, or through the Selenium Server.
GeckoDriver
Overview
GeckoDriver is a standalone application used to interact with Gecko-based browsers, such as Firefox. It is written in Rust and maintained by Mozilla.
Starting with Firefox 48, GeckoDriver is the only way to automate Firefox, the legacy FirefoxDriver which used to be part of Selenium is no longer supported. Internally it translates the HTTP calls into Marionette, Mozilla's automation protocol built into Firefox.
Download
Binaries are available for download on the GeckoDriver Releases page on GitHub, for various platforms.
Selenium 2.x users are advised to use version v0.9, whereas Selenium 3 users should use the latest version.
Usage
If you're using GeckoDriver through Selenium Server, simply set the cli argument "webdriver.gecko.driver" to point to the location of the binary file. E.g.:
{
"selenium" : {
"start_process" : true,
"server_path" : "./bin/selenium-server-standalone-3.{VERSION}.jar",
"log_path" : "",
"port" : 4444,
"cli_args" : {
"webdriver.gecko.driver" : "./bin/geckodriver"
}
}
}
GeckoDriver can also be used as a standalone application. Usage steps are documented on GitHub: https://github.com/mozilla/geckodriver#usage.
Command line usage
$ ./bin/geckodriver-0.10 -help
geckodriver 0.10.0
USAGE:
geckodriver-0.10 [FLAGS] [OPTIONS]
FLAGS:
--connect-existing Connect to an existing Firefox instance
-h, --help Prints help information
--no-e10s Start Firefox without multiprocess support (e10s) enabled
-V, --version Prints version information
-v Set the level of verbosity. Pass once for debug level logging and twice for trace level logging
OPTIONS:
-b, --binary Path to the Firefox binary, if no binary capability provided
--log Set Gecko log level [values: fatal, error, warn, info, config, debug, trace]
--marionette-port Port to use to connect to gecko (default: random free port)
--host Host ip to use for WebDriver server (default: 127.0.0.1)
-p, --port Port to use for WebDriver server (default: 4444)
Firefox Capabilities
GeckoDriver supports a capability named firefoxOptions which takes Firefox-specific preference values. Details are available on the GeckoDriver GitHub page: https://github.com/mozilla/geckodriver#firefox-capabilities.
Firefox Profile
Specifying the firefox profile can be done by setting the profile property in the firefoxOptions dictionary, as detailed above. This can be the base64-encoded zip of a profile directory and it may be used to install extensions or custom certificates.
Implementation Status
GeckoDriver is not yet feature complete, which means it does not yet offer full conformance with the WebDriver standard or complete compatibility with Selenium. Implementation status can be tracked on the Marionette MDN page.
ChromeDriver
Overview
ChromeDriver is a standalone server which implements the W3C WebDriver wire protocol for Chromium. ChromeDriver is available for Chrome on Android and Chrome on Desktop (Mac, Linux, Windows and ChromeOS).
Download
Binaries are available for download on the ChromeDriver Downloads page, for various platforms.
Selenium Server Usage
If you're using ChromeDriver through Selenium Server, simply set the cli argument "webdriver.chrome.driver" to point to the location of the binary file. E.g.:
{
"selenium" : {
"start_process" : true,
"server_path" : "./bin/selenium-server-standalone-3.{VERSION}.jar",
"log_path" : "",
"port" : 4444,
"cli_args" : {
"webdriver.chrome.driver" : "./bin/chromedriver"
}
}
}
Standalone Usage
If you're only running your tests against Chrome, running ChromeDriver standalone is easier and slightly faster. Also there is no dependency on Java.
This requires a bit more configuration:
1) First, disable Selenium Server, if applicable:
{
"selenium" : {
"start_process" : false
}
}
2) Configure the port and default path prefix.
ChromeDriver runs by default on port 9515. We also need to clear the default_path_prefix, as it is set by default to /wd/hub, which is what selenium is using.
{
"test_settings" : {
"default" : {
"selenium_port" : 9515,
"selenium_host" : "localhost",
"default_path_prefix" : "",
"desiredCapabilities": {
"browserName": "chrome",
"chromeOptions" : {
"args" : ["--no-sandbox"]
},
"acceptSslCerts": true
}
}
}
}
3) Start the ChromeDriver server
The easiest way to manage the ChromeDriver process is by using the chromedriver NPM package, which is a third-party wrapper against the binary. This will abstract the downloading of the chromedriver binary and will make it easy to manage starting and stopping of the process.
You can add this to your external globals file, like so:
var chromedriver = require('chromedriver');
module.exports = {
before : function(done) {
chromedriver.start();
done();
},
after : function(done) {
chromedriver.stop();
done();
}
};
Using a fixed ChromeDriver version
In some situations you may need to use a specific version of ChromeDriver. For instance, the CI server runs an older version of Chrome. Then you will need an older version of ChromeDriver.
Here's what your globals file might look like:
var chromedriver = require('chromedriver');
var path = require('path');
var driverInstanceCI;
function isRunningInCI() {
return this.test_settings.globals.integration;
}
function startChromeDriver() {
if (isRunningInCI.call(this)) {
var location = path.join(__dirname, '../bin/chromedriver-linux64-2.17');
driverInstanceCI = require('child_process').execFile(location, []);
return;
}
chromedriver.start();
}
function stopChromeDriver() {
if (isRunningInCI.call(this)) {
driverInstanceCI && driverInstanceCI.kill();
return;
}
chromedriver.stop();
}
module.exports = {
'ci-server' : {
integration : true
},
before : function(done) {
startChromeDriver.call(this);
done();
},
after : function(done) {
stopChromeDriver.call(this);
done();
}
};
Run your tests then with (on the CI server):
$ ./node_modules/.bin/nightwatch --env ci-server
ChromeOptions
You can specify Chrome options or switches using the chromeOptions dictionary, under the desiredCapabilities. Refer to the ChromeDriver website for a fill list of supported capabilities and options.
Command line usage
$ ./bin/chromedriver -h
Usage: ./bin/chromedriver [OPTIONS]
Options
--port=PORT port to listen on
--adb-port=PORT adb server port
--log-path=FILE write server log to file instead of stderr, increases log level to INFO
--verbose log verbosely
--version print the version number and exit
--silent log nothing
--url-base base URL path prefix for commands, e.g. wd/url
--port-server address of server to contact for reserving a port
--whitelisted-ips comma-separated whitelist of remote IPv4 addresses which are allowed to connect to ChromeDriver
Microsoft WebDriver
Overview
Microsoft WebDriver is a standalone server which implements the W3C WebDriver wire protocol for the Edge browser. It is supported by Windows 10 and onwards.
Download
Binaries are available for download on the Microsoft WebDriver homepage.
Selenium Server Usage
If you're using Microsoft WebDriver through Selenium Server, simply set the cli argument "webdriver.edge.driver" to point to the location of the binary file. E.g.:
{
"selenium" : {
"start_process" : true,
"server_path" : "bin/selenium-server-standalone-3.{VERSION}.jar",
"log_path" : "",
"port" : 4444,
"cli_args" : {
"webdriver.edge.driver" : "bin/MicrosoftWebDriver.exe"
}
},
"test_settings" : {
"default" : {
"selenium_port" : 4444,
"selenium_host" : "localhost",
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"acceptSslCerts": true
}
}
}
}
Standalone Usage
If you're only running your tests against Edge, running the EdgeDriver standalone can be slightly faster. Also there is no dependency on Java.
This requires a bit more configuration and you will need to start/stop the EdgeDriver:
1) First, disable Selenium Server, if applicable:
{
"selenium" : {
"start_process" : false
}
}
2) Configure the port and default path prefix.
Microsoft WebDriver runs by default on port 9515. We also need to clear the default_path_prefix, as it is set by default to /wd/hub, which is what selenium is using.
{
"test_settings" : {
"default" : {
"selenium_port" : 17556,
"selenium_host" : "localhost",
"default_path_prefix" : "",
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"acceptSslCerts": true
}
}
}
}
3) Start the MicrosoftWebDriver server
From the Windows CMD prompt, simply CD to the folder where the MicrosoftWebDriver.exe binary is located and run:
C:\nightwatch\bin>MicrosoftWebDriver.exe
[13:44:49.515] - Listening on http://localhost:17556/
Full command line usage:
C:\nightwatch\bin>MicrosoftWebDriver.exe -h
Usage:
MicrosoftWebDriver.exe --host= --port= --package= --verbose
Implementation Status
EdgeDriver is not yet feature complete, which means it does not yet offer full conformance with the WebDriver standard or complete compatibility with Selenium. Implementation status can be tracked on the Microsoft WebDriver homepage.
Developer Guide
Using Nightwatch
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.
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')
};
BDD Expect Assertions
Nightwatch introduces starting with version v0.7 a new BDD-style assertion library which greatly improves the flexibility as well as readability of the assertions.
The expect assertions use a subset of the Expect api from the Chai framework and are available for elements only at this point. Here's an example:
module.exports = {
'Demo test Google' : function (client) {
client
.url('http://google.no')
.pause(1000);
// expect element to be present in 1000ms
client.expect.element('body').to.be.present.before(1000);
// expect element <#lst-ib> to have css property 'display'
client.expect.element('#lst-ib').to.have.css('display');
// expect element to have attribute 'class' which contains text 'vasq'
client.expect.element('body').to.have.attribute('class').which.contains('vasq');
// expect element <#lst-ib> to be an input tag
client.expect.element('#lst-ib').to.be.an('input');
// expect element <#lst-ib> to be visible
client.expect.element('#lst-ib').to.be.visible;
client.end();
}
};
The expect interface provides a much more flexible and fluid language for defining assertions, significantly improved over the existing assert interface. The only downside is that it's not possible to chain assertions anymore and at this point custom messages aren't yet supported.
For a complete list of available expect assertions, refer to the API docs.
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() {
},
'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().
For backwards compatibility reasons, the afterEach hook can receive the browser object only in its async form - afterEach(browser, done) { .. }
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.
done function must be called as the last step when the async operation completes. Not calling it will result in a timeout error.
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);
}
};
Controlling the done invocation timeout
By default the done invocation timeout is set to 10 seconds (2 seconds for unit tests). In some cases this might not be sufficient and to avoid a timeout error, you can increase this timeout by defining an asyncHookTimeout property (in milliseconds) in your external globals file (see below for details on external globals).
For an example, refer to the provided globalsModule example.
Explicitly failing the test
Failing the test intentionally in a test hook is achievable by simply calling done with an Error argument:
module.exports = {
afterEach: function(browser, done) {
// performing an async operation
performAsync(function(err) {
if (err) {
done(err);
}
// ...
});
}
};
External Globals
Most of the time it's more useful to have your globals defined in an external file, specified in the globals_path property, instead of having them defined in nightwatch.json.
You can overwrite globals per environment as needed. Say you have your tests running locally and also against a remote staging server. Most of the times you will need some different setting up.
Global Hooks
The same set of hooks as per test suite is also available globally, outside the scope of the test. See the below example for more details.
In the case of global hooks, the beforeEach and afterEach refers to a test suite (i.e. test file), and are ran before and after a test suite.
Global Settings
There are a number of globals which are holding test settings and can control test execution. These are detailed in the provided globalsModule sample.
Example:
module.exports = {
'default' : {
isLocal : true,
},
'integration' : {
isLocal : false
},
// External before hook is ran at the beginning of the tests run, before creating the Selenium session
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();
}
},
// External after hook is ran at the very end of the tests run, after closing the Selenium session
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();
}
},
// This will be run before each test suite is started
beforeEach: function(browser, done) {
// getting the session info
browser.status(function(result) {
console.log(result.value);
done();
});
},
// This will be run after each test suite is finished
afterEach: function(browser, done) {
console.log(browser.currentTest);
done();
}
};
Running Tests
Test Runner
Nightwatch includes a command-line test runner which makes it easy to run tests and generate useful output. There are a few different options on how to use the test runner, depending on your installation type.
Global
If you have installed Nightwatch globally (with -g option), the binary nightwatch will be available anywhere:
$ nightwatch [source] [options]
Project specific
If you have Nightwatch installed as a dependency of your project, you can refer the binary from the node_modules/.bin folder:
Linux and MacOSX:
$ ./node_modules/.bin/nightwatch [source] [options]
Windows:
Create a file nightwatch.js and add the following line:
require('nightwatch/bin/runner.js');
Then run as follows:
C:\workspace\project> node nightwatch.js [source] [options]
Tests source
The optional source argument can be either one or more files or an entire folder. This can be located irrespectively of the src_folders setting.
Example - single test:
$ nightwatch tests/one/firstTest.js
Example - 2 individual tests:
$ nightwatch tests/one/firstTest.js tests/secondTest.js
Example - 1 individual test and 1 folder:
$ nightwatch tests/one/test.js tests/utils
Command-line Options
The test runner supports a number of run-time options to be passed to. 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 |
|
Shows extended selenium command logging during the session | |
--version |
-v |
Shows the version number | |
--test |
-t |
Runs only the specified test suite/module. By default the runner will attempt to run all tests in the src_folders settings folder(s) and their 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. | |
--tag |
-a |
Filter test modules by tags. Only tests that have the specified tags will be loaded. | |
--skiptags |
Skips tests that have the specified tag or tags (comma separated). | ||
--retries |
Retries failed or errored testcases up to the specified number of times. Retrying a testcase will also retry the beforeEach and afterEach hooks, if any. |
||
--suiteRetries |
Retries failed or errored testsuites (test modules) up to the specified number of times. Retrying a testsuite will also retry the before and after hooks (in addition to the global beforeEach and afterEach respectively), if any are defined on the testsuite. |
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 the @tags 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
To skip running tests with a specific tag, use the --skiptags flag:
$ nightwatch --skiptags login
Or to skip multiple tags, add each tag you want to skip as comma-separated:
$ nightwatch --skiptags login,something_else
Disabling Tests
To prevent a test module from running, simply set the disabled attribute in that module to true, like so:
module.exports = {
'@disabled': true, // This will prevent the test module from running.
'sample test': function (client) {
// test code
}
};
This can be useful if you don't want to run certain tests that are known to be failing.
Disabling Individual Testcases
Disabling individual testcases isn't currently supported out of the box. However it can be achieved relatively straightforward with a simple work-around. By simply converting the test method to a string, Nightwatch will ignore it.
Here's an example:
module.exports = {
'sample test': function (client) {
// test code
},
// disabled
'other sample test': ''+function (client) {
// test code
}
};
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.
"live_output" : true on the top level in your nightwatch.json (e.g. after selenium).
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.
Via Workers
Version v0.7 introduces a new feature which allows the tests to be run in parallel. When this is enabled the test runner will launch a configurable number of child processes and then distribute the loaded tests over to be ran in parallel.
To enable test workers, set the test_workers top-level property, like so:
"test_workers": {
"enabled": true,
"workers": "auto"
}
or, simply:
"test_workers": true
The
workers option configures how many child processes can run concurrently.
"auto"- determined by number of CPUs e.g. 4 CPUs means 4 workers{number}- specifies an exact number of workers
Test concurrency is done at the file level. Each test file will fill a test worker slot. Individual tests/steps in a test file will not run concurrently.
detailed_output to false in your test settings for improved output readability.
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 or 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 iscwd- current working directoryargv- 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.
Using Mocha
Starting with version 0.8 Nightwatch is bundled with a custom version of the popular Mocha test runner which allows running tests using Mocha, thus taking advantage of its interfaces and reporters.
Usage
There are two main ways in which you can use Mocha with Nightwatch.
From Nightwatch
Mocha is used as an alternative test runner to the built-in one. This is done by specifying the "test_runner" option in the nightwatch.json configuration file.
Custom options can also be specified for Mocha:
{
...
"test_runner" : {
"type" : "mocha",
"options" : {
"ui" : "bdd",
"reporter" : "list"
}
}
...
}
or simply:
{
...
"test_runner" : "mocha"
...
}
A complete list of Mocha options that are supported can be found here.
The test_runner option can also be specified at test environment level:
{
"test_settings" : {
"mocha_tests" : {
"test_runner" : {
"type" : "mocha",
"options" : {
"ui" : "tdd",
"reporter" : "list"
}
}
}
}
...
}
Example
Writing a test in Mocha is the same as writing it in Nightwatch. Each testcase receives the client object, hooks also receiving a done callback for async operations.
describe('Google demo test for Mocha', function() {
describe('with Nightwatch', function() {
before(function(client, done) {
done();
});
after(function(client, done) {
client.end(function() {
done();
});
});
afterEach(function(client, done) {
done();
});
beforeEach(function(client, done) {
done();
});
it('uses BDD to run the Google simple test', function(client) {
client
.url('http://google.com')
.expect.element('body').to.be.present.before(1000);
client.setValue('input[type=text]', ['nightwatch', client.Keys.ENTER])
.pause(1000)
.assert.containsText('#main', 'Night Watch');
});
});
});
When using the mocha test runner from Nightwatch some cli options are not available, like --retries, --suiteRetries, --reporter.
Using the standard Mocha
Running Nightwatch tests with the standard Mocha it's also possible, though a bit more boilerplate code is involved and you need to manage the selenium server.
Example
var nightwatch = require('nightwatch');
describe('Github', function() {
var client = nightwatch.initClient({
silent : true
});
var browser = client.api();
this.timeout(99999999);
before(function() {
browser.perform(function() {
console.log('beforeAll')
});
});
beforeEach(function(done) {
browser.perform(function() {
console.log('beforeEach')
});
client.start(done);
});
it('Demo test GitHub', function (done) {
browser
.url('https://github.com/nightwatchjs/nightwatch')
.waitForElementVisible('body', 5000)
.assert.title('nightwatchjs/nightwatch · GitHub')
.waitForElementVisible('body', 1000)
.assert.visible('.container .breadcrumb a span')
.assert.containsText('.container .breadcrumb a span', 'nightwatch', 'Checking project title is set to nightwatch');
client.start(done);
});
afterEach(function() {
browser.perform(function() {
console.log('afterEach')
});
});
after(function(done) {
browser.end(function() {
console.log('afterAll')
});
client.start(done);
});
});
Working with Page Objects
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 comprehensive introduction to Page Objects can be found in this article.
0.7 Nightwatch provides an enhanced and more powerful interface for creating page objects, significantly improved over the previous support. Page objects created prior to v0.7 will still continue to work however we recommend upgrading to the new version.
To use the new version, your page object must contain either the elements or sections property. Otherwise, Nightwatch will defer to the old.
Configuring Page Objects
To create a page object simply create an object with properties that describe the page. Each page object should be located in a separate file, located in a designated folder. Nightwatch reads the page objects from the folder (or folders) 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.
The Url property
You can optionally add a url property that designates the page's URL. To navigate to the page, you can call the navigate method on the page object.
The URL will usually be defined as a string:
module.exports = {
url: 'http://google.com',
elements: {}
};
It can also be a function in case the URL is dynamic. One use case for this is to support different test environments. You can create a function that gets called in the context of the page, thus allowing you to do:
module.exports = {
url: function() {
return this.api.launchUrl + '/login';
},
elements: {}
};
Defining Elements
Most of the time, you will want to define elements on your page that your tests will interact with through commands and assertions. This is made simple using the elements property so that all your elements are defined in a single place. Especially in larger integration tests, using elements will go a long way to keep test code DRY.
Switching between css and xpath locate strategies is handled internally so you don't need to call useXpath and useCss in your tests. The default locateStrategy is css but you can also specify xpath:
module.exports = {
elements: {
searchBar: {
selector: 'input[type=text]'
},
submit: {
selector: '//[@name="q"]',
locateStrategy: 'xpath'
}
}
};
Or if you're creating elements with the same locate strategy as is default, you can use the shorthand:
module.exports = {
elements: {
searchBar: 'input[type=text]'
}
};
Using the elements property allows you to refer to the element by its name with an "@" prefix, rather than selector, when calling element commands and assertions (click, etc).
Optionally, you can define an array of objects:
var sharedElements = {
mailLink: 'a[href*="mail.google.com"]'
};
module.exports = {
elements: [
sharedElements,
{ searchBar: 'input[type=text]' }
]
};
Putting elements and url together, say you have the following defined above saved as a google.js file:
module.exports = {
url: 'http://google.com',
elements: {
searchBar: {
selector: 'input[type=text]'
},
submit: {
selector: '//[@name="q"]',
locateStrategy: 'xpath'
}
}
};
In your tests you will use it as follows:
module.exports = {
'Test': function (client) {
var google = client.page.google();
google.navigate()
.assert.title('Google')
.assert.visible('@searchBar')
.setValue('@searchBar', 'nightwatch')
.click('@submit');
client.end();
}
};
Defining Sections
Sometimes it is useful to define sections of a page. Sections do 2 things:
- Provide a level of namespacing under the page
- Provide element-level nesting so that any element defined within a section is a descendant of its parent section in the DOM
You can create sections using the sections property:
module.exports = {
sections: {
menu: {
selector: '#gb',
elements: {
mail: {
selector: 'a[href="mail"]'
},
images: {
selector: 'a[href="imghp"]'
}
}
}
}
};
Your tests would use it as follows:
module.exports = {
'Test': function (client) {
var google = client.page.google();
google.expect.section('@menu').to.be.visible;
var menuSection = google.section.menu;
menuSection.expect.element('@mail').to.be.visible;
menuSection.expect.element('@images').to.be.visible;
menuSection.click('@mail');
client.end();
}
};
expect assertions) returns that section for chaining. If desired, you can nest sections under other sections for complex DOM structures.
Example of nesting page object sections:
module.exports = {
sections: {
menu: {
selector: '#gb',
elements: {
mail: {
selector: 'a[href="mail"]'
},
images: {
selector: 'a[href="imghp"]'
}
},
sections: {
apps: {
selector: 'div.gb_pc',
elements: {
myAccount: {
selector: '#gb192'
},
googlePlus: {
selector: '#gb119'
}
}
}
}
}
}
};
Using a nested section in your test is straightforward:
module.exports = {
'Test': function (client) {
var google = client.page.google();
google.expect.section('@menu').to.be.visible;
var menuSection = google.section.menu;
var appSection = menuSection.section.apps;
menuSection.click('@appSection');
appSection.expect.element('@myAccount').to.be.visible;
appSection.expect.element('@googlePlus').to.be.visible;
client.end();
}
};
Writing Commands
You can add commands to your page object using the commands property. This is a useful way to encapsulate logic about the page that would otherwise live in a test, or multiple tests.
Nightwatch will call the command on the context of the page or section. Client commands like pause are available via this.api. For chaining, each function should return the page object or section.
In this case, a command is used to encapsulate logic for clicking the submit button:
var googleCommands = {
submit: function() {
this.api.pause(1000);
return this.waitForElementVisible('@submitButton', 1000)
.click('@submitButton')
.waitForElementNotPresent('@submitButton');
}
};
module.exports = {
commands: [googleCommands],
elements: {
searchBar: {
selector: 'input[type=text]'
},
submitButton: {
selector: 'button[name=btnG]'
}
}
};
Then the test is simply:
module.exports = {
'Test': function (client) {
var google = client.page.google();
google.setValue('@searchBar', 'nightwatch')
.submit();
client.end();
}
};
Extending 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 own commands inside there, 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.
There are two main ways in which you can define a custom command:
1) Function-style commands
This is the simplest form in which commands are defined, however they are also quite limited. Your command module needs to export a command function, which needs to call at least one Nightwatch api method (such as .execute()). This is due to a limitation of how the asynchronous queueing system of commands works. You can also wrap everything in a .perform() call. Client commands like execute and perform are available via this.
exports.command = function(file, callback) {
var self = this;
var imageData;
var 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;
};
The example above defines a command (e.g. resizePicture.js) which loads an image file as data-URI and calls a method named resizePicture (via .execute()), 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();
}
};
2) Class-style commands
This is how most of the Nightwatch's own commands are written. Your command module needs to export a class constructor with a command instance method representing the command function. Commands written like this should inherit from EventEmitter and manually signal the complete event, to indicate command completion.
Class-based command methods are run in the context (the value of this) of the class instance. The test api object is available as this.api or this.client.api, where this.client is the Nightwatch instance itself.
The example below is the .pause() command:
var util = require('util');
var events = require('events');
function Pause() {
events.EventEmitter.call(this);
}
util.inherits(Pause, events.EventEmitter);
Pause.prototype.command = function(ms, cb) {
var self = this;
// If we don't pass the milliseconds, the client will
// be suspended indefinitely
if (!ms) {
return this;
}
setTimeout(function() {
// if we have a callback, call it right before the complete event
if (cb) {
cb.call(self.client.api);
}
self.emit('complete');
}, ms);
return this;
};
module.exports = Pause;
The "complete" event
Signaling the complete event needs to be done inside an asynchronous action (e.g. a setTimeout call). Command classes that do not extend EventEmitter will be treated similar to command functions, requiring that the command method calls at least one Nightwatch api method to be able to complete.
Using ES6 classes as custom commands is not supported at the moment. See nightwatchjs#1199 for more details.
Writing Custom Assertions
Nightwatch allows you to even define your own assertions, extending the available .assert and .verify namespaces.
Assertions implement a simple interface which is shared between built-in assertions and custom ones:
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;
};
};
Custom assertions also inherit from EventEmitter. To see some examples, check the assertions module 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();
}
};
Unit Testing with Nightwatch
Writing Unit Tests
Unit testing in Nightwatch has been refined in version 0.9. Unit tests now written in Nightwatch are also fully compatible with Mocha's Exports interface, so you can use either test runners. In fact, all Nightwatch's unit tests have been rewritten so they can be ran with either Nightwatch or Mocha.
compatible_testcase_support to true in your test settings.
Unit tests written in versions prior to 0.9 will still continue to work however we recommend upgrading them.
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
Starting with 0.9, in the improved support for unit tests, the client object is no longer passed as an argument to the test. The only argument passed now is the done callback to be used for asynchronous tests.
You can use whatever assertion framework you like. Chai.js is quite a good one and very flexible. We use the internal Node.js assert module in the Nightwatch unit tests.
You can still refer the client object via this.client in your tests.
Example
Here's a subset of the unit test for the utils.js Nightwatch module:
var assert = require('assert');
var common = require('../../common.js');
var Utils = common.require('util/utils.js');
module.exports = {
'test Utils' : {
testFormatElapsedTime : function() {
var resultMs = Utils.formatElapsedTime(999);
assert.equal(resultMs, '999ms');
var resultSec = Utils.formatElapsedTime(1999);
assert.equal(resultSec, '1.999s');
var resultMin = Utils.formatElapsedTime(122299, true);
assert.equal(resultMin, '2m 2s / 122299ms');
},
testMakeFnAsync : function() {
function asyncFn(cb) {
cb();
}
function syncFn() {}
var convertedFn = Utils.makeFnAsync(1, syncFn);
var called = false;
convertedFn(function() {
called = true;
});
assert.equal(Utils.makeFnAsync(1, asyncFn), asyncFn);
assert.ok(called);
}
}
};
Asynchronous Unit Tests
The argument to the test function is the optional done callback which signals the test is complete.
If present, the callback must be called when the async operation finishes.
Example
Here's unit test which checks if Nightwatch throws an error if you don't invoke the done callback within a set time (10 ms).
module.exports = {
var path = require('path');
var assert = require('assert');
var common = require('../../common.js');
var CommandGlobals = require('../../lib/globals/commands.js');
var Runner = common.require('runner/run.js');
module.exports = {
'testRunner': {
before: function (done) {
CommandGlobals.beforeEach.call(this, done);
},
after: function (done) {
CommandGlobals.afterEach.call(this, done);
},
beforeEach: function () {
process.removeAllListeners('exit');
process.removeAllListeners('uncaughtException');
},
'test async unit test with timeout error': function (done) {
var testsPath = path.join(__dirname, '../../asynchookstests/unittest-async-timeout.js');
var globals = {
calls : 0,
asyncHookTimeout: 10
};
process.on('uncaughtException', function (err) {
assert.ok(err instanceof Error);
assert.equal(err.message, 'done() callback timeout of 10 ms was reached while executing "demoTest". ' +
'Make sure to call the done() callback when the operation finishes.');
done();
});
var runner = new Runner([testsPath], {
seleniumPort: 10195,
silent: true,
output: false,
persist_globals : true,
globals: globals,
compatible_testcase_support : true
}, {
output_folder : false,
start_session : false
});
runner.run().catch(function(err) {
done(err);
});
}
}
};
};
The complete test suite can be viewed on GitHub: https://github.com/nightwatchjs/nightwatch/tree/master/test/src/runner/testRunner.js
Running the Nightwatch unit tests
To get an idea of how running unit tests with Nightwatch works you can head over to our GitHub page, clone the project and follow the instructions on how to run the tests.
You can also check out Nightwatch's own complete test suite for examples: https://github.com/nightwatchjs/nightwatch/tree/master/test/src
Here's the configuration needed to run them:
{
"src_folders" : ["./test/src"],
"selenium" : {
"start_process" : false,
"start_session" : false
},
"test_settings" : {
"default" : {
"filter" : "*/.js",
"compatible_testcase_support" : true
}
}
}
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" : ""
}
}
}
Code Coverage
At the moment, Nightwatch doesn't provide a coverage reporter but it is something that's being planned for a future release. In the meantime you can write a custom reporter which will output coverage data. See the custom reporter section for details and the Mocha HTMLCov reporter for how the reporter should look like.
3rd party coverage service
There are some hosted services which provide the reporting and metrics for you in a modern web interface. These services will typically require coverage data in LCOV format. Nightwatch uses coveralls.io.
For details on how an LCOV reporter should look like and how to integrate with your project, you can check out the mocha-lcov-reporter.
API Reference
Expect
Nightwatch introduces in version 0.7 a new BDD-style interface for performing assertions on elements, defined on the expect namespace on the main Nightwatch instance. It is based on the Chai Expect assertion library and provides a greater level of flexibility and adds new capabilities over the classic assert interface.
It uses a chainable language to construct assertions given an element specified by a css/xpath selector. A simple example looks like the following:
this.demoTest = function (browser) {
// start with identifying the element
// and then assert the element is present
browser.expect.element('#main').to.be.present;
// or assert the element is visible
browser.expect.element('#main').to.be.visible;
};
Language Chains
The following are provided as chainable getters to improve the readability of your assertions. They do not provide testing capabilities and the order is not important.
- to
- be
- been
- is
- that
- which
- and
- has
- have
- with
- at
- does
- of
.equal(value)/.contain(value)/.match(regex)
These methods will perform assertions on the specified target on the current element. The targets can be an attribute value, the element's inner text and a css property.
this.demoTest = function (browser) {
browser.expect.element('#main').text.to.equal('The Night Watch');
browser.expect.element('#main').text.to.contain('The Night Watch');
browser.expect.element('#main').to.have.css('display').which.equals('block');
};
.not
Negates any of assertions following in the chain.
this.demoTest = function (browser) {
browser.expect.element('#main').text.to.not.equal('The Night Watch');
browser.expect.element('#main').text.to.not.contain('The Night Watch');
browser.expect.element('#main').to.have.css('display').which.does.not.equal('block');
};
.before(ms)/.after(ms)
These methods perform the same thing which is essentially retrying the assertion for the given amount of time (in milliseconds). before or after can be chained to any assertion and thus adding retry capability.
You can change the polling interval by defining a waitForConditionPollInterval property (in milliseconds) as a global property in your nightwatch.json or in your external globals file.
Similarly, a default timeout can be specified as a global waitForConditionTimeout property (in milliseconds).
this.demoTest = function (browser) {
browser.expect.element('#main').text.to.contain('The Night Watch').before(1000);
browser.expect.element('#main').text.to.not.contain('The Night Watch').after(500);
};
.a(type)
Checks if the type (i.e. tag name) of a specified element is of an expected value.
Parameters:
| Name | Type | description |
|---|---|---|
type |
string | The expected type |
messageOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.expect.element('#q').to.be.an('input');
browser.expect.element('#q').to.be.an('input', 'Testing if #q is an input');
browser.expect.element('#w').to.be.a('span');
};
.attribute(name)
Checks if a given attribute of an element exists and optionally if it has the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
attribute |
string | The attribute name |
messageOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.expect.element('body').to.have.attribute('data-attr');
browser.expect.element('body').to.not.have.attribute('data-attr');
browser.expect.element('body').to.not.have.attribute('data-attr', 'Testing if body does not have data-attr');
browser.expect.element('body').to.have.attribute('data-attr').before(100);
browser.expect.element('body').to.have.attribute('data-attr')
.equals('some attribute');
browser.expect.element('body').to.have.attribute('data-attr')
.not.equals('other attribute');
browser.expect.element('body').to.have.attribute('data-attr')
.which.contains('something');
browser.expect.element('body').to.have.attribute('data-attr')
.which.matches(/^something\ else/);
};
.css(property)
Checks a given css property of an element exists and optionally if it has the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
property |
string | The css property name |
messageOptional |
string | Optional log message to display in the output. If missing, one is displayed by default.* |
Usage:
this.demoTest = function (browser) {
browser.expect.element('#main').to.have.css('display');
browser.expect.element('#main').to.have.css('display', 'Testing for display');
browser.expect.element('#main').to.not.have.css('display');
browser.expect.element('#main').to.have.css('display').before(100);
browser.expect.element('#main').to.have.css('display').which.equals('block');
browser.expect.element('#main').to.have.css('display').which.contains('some value');
browser.expect.element('#main').to.have.css('display').which.matches(/some\ value/);
};
.enabled
Property that checks if an element is currently enabled.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#weblogin').to.be.enabled;
browser.expect.element('#main').to.not.be.enabled;
browser.expect.element('#main').to.be.enabled.before(100);
};
.present
Property that checks if an element is present in the DOM.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#main').to.be.present;
browser.expect.element('#main').to.not.be.present;
browser.expect.element('#main').to.be.present.before(100);
};
.selected
Property that checks if an OPTION element, or an INPUT element of type checkbox or radio button is currently selected.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#main').to.be.selected;
browser.expect.element('#main').to.not.be.selected;
browser.expect.element('#main').to.be.selected.before(100);
};
.text
Property that retrieves the text contained by an element. Can be chained to check if contains/equals/matches the specified text or regex.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#main').text.to.equal('The Night Watch');
browser.expect.element('#main').text.to.not.equal('The Night Watch');
browser.expect.element('#main').text.to.equal('The Night Watch').before(100);
browser.expect.element('#main').text.to.contain('The Night Watch');
browser.expect.element('#main').text.to.match(/The\ Night\ Watch/);
};
.value
Property that retrieves the value (i.e. the value attributed) of an element. Can be chained to check if contains/equals/matches the specified text or regex.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#q').to.have.value.that.equals('search');
browser.expect.element('#q').to.have.value.not.equals('search');
browser.expect.element('#q').to.have.value.which.contains('search');
browser.expect.element('#q').to.have.value.which.matches(/search/);
};
.visible
Property that asserts the visibility of a specified element.
Usage:
this.demoTest = function (browser) {
browser.expect.element('#main').to.be.visible;
browser.expect.element('#main').to.not.be.visible;
browser.expect.element('#main').to.be.visible.before(100);
};
Assert
The classic assert/verify library is still available on the Nightwatch instance as two objects containing the same methods to perform assertions on elements:
.assert- when an assertion fails, the test ends, skipping all other assertions..verify- when an assertion fails, the test logs the failure and continues with other assertions.
This will end the test:
client.assert.visible('.non_existing');
But this will just log the failure and continue:
client.verify.visible(".non_existing");
Node.js Assert Module
Nightwatch.js extends Node.js assert module, so you can also use any of the available methods there in your tests.
Automatically retrying failed assertions
You can tell Nightwatch to automatically retry failed assertions until a given timeout is reached, before the test runner gives up and fails the test.
This can be accomplished by setting the property retryAssertionTimeout (in milliseconds) in the globals file.
For example: retryAssertionTimeout = 2000
.attributeContains()
Checks if the given attribute of an element contains the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The selector (CSS / Xpath) used to locate the element. |
attribute |
string | The attribute name |
expected |
string | The expected contained value of the attribute to check. |
messageOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.attributeContains('#someElement', 'href', 'google.com');
};
.attributeEquals()
Checks if the given attribute of an element has the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
attribute |
string | The attribute name |
expected |
string | The expected value of the attribute to check. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.attributeEquals("body", "data-attr", "some value");
};
.containsText()
Checks if the given element contains the specified text.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
expectedText |
string | The text to look for. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.containsText("#main", "The Night Watch");
};
.cssClassPresent()
Checks if the given element has the specified CSS class.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
className |
string | The CSS class to look for. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.cssClassPresent("#main", "container");
};
.cssClassNotPresent()
Checks if the given element does not have the specified CSS class.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
className |
string | The CSS class to look for. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.cssClassNotPresent("#main", "container");
};
.cssProperty()
Checks if the specified css property of a given element has the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
cssProperty |
string | The CSS property. |
expected |
string|number | The expected value of the css property to check. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.cssProperty("#main", "display", "block");
};
.elementPresent()
Checks if the given element exists in the DOM.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.elementPresent("#main");
};
.elementNotPresent()
Checks if the given element does not exist in the DOM.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.elementNotPresent(".should_not_exist");
};
.hidden()
Checks if the given element is not visible on the page.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.hidden(".should_not_be_visible");
};
.title()
Checks if the page title equals the given value.
Parameters:
| Name | Type | description |
|---|---|---|
expected |
string | The expected page title. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.title("Nightwatch.js");
};
.urlContains()
Checks if the current URL contains the given value.
Parameters:
| Name | Type | description |
|---|---|---|
expectedText |
string | The value expected to exist within the current URL. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.urlContains('google');
};
.urlEquals()
Checks if the current url equals the given value.
Parameters:
| Name | Type | description |
|---|---|---|
expected |
string | The expected url. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.urlEquals('http://www.google.com');
};
.value()
Checks if the given form element's value equals the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
expectedText |
string | The expected text. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.value("form.login input[type=text]", "username");
};
.valueContains()
Checks if the given form element's value contains the expected value.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
expectedText |
string | The expected text. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.valueContains("form.login input[type=text]", "username");
};
.visible()
Checks if the given element is visible on the page.
Parameters:
| Name | Type | description |
|---|---|---|
cssSelector |
string | The CSS selector used to locate the element. |
msgOptional |
string | Optional log message to display in the output. If missing, one is displayed by default. |
Usage:
this.demoTest = function (browser) {
browser.assert.visible(".should_be_visible");
};
Commands
The commands are convenience methods for performing various operations on the page and usually incorporate two or more WebDriver protocol actions.
The callback function
Each method below allows an optional callback argument to be passed as the last argument. The callback function will then be called after the command is completed
with the main instance as the context and the response object as argument.
this.demoTest = function (browser) {
browser.click("#main ul li a.first", function(response) {
this.assert.ok(browser === this, "Check if the context is right.");
this.assert.ok(typeof response == "object", "We got a response object.");
});
};.clearValue()
Clear a textarea or a text input element's value. Uses elementIdValue protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (client) {
client.clearValue('input[type=text]');
};
.click()
Simulates a click event on the given DOM element. Uses elementIdClick protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (client) {
client.click("#main ul li a.first");
};
.closeWindow()
Close the current window. This can be useful when you're working with multiple windows open (e.g. an OAuth login).
Uses window protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (client) {
client.closeWindow();
};
.deleteCookie()
Delete the cookie with the given name. This command is a no-op if there is no such cookie visible to the current page.
Parameters:
| Name | Type | description |
|---|---|---|
The |
cookieName | name of the cookie to delete. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function(browser) {
browser.deleteCookie("test_cookie", function() {
// do something more in here
});
}
.deleteCookies()
Delete all cookies visible to the current page.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function(browser) {
browser.deleteCookies(function() {
// do something more in here
});
}
.end()
Ends the session. Uses session protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.end();
};
.getAttribute()
Retrieve the value of an attribute for a given DOM element. Uses elementIdAttribute protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
attribute |
string | The attribute name to inspect. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| * | The value of the attribute |
Usage:
this.demoTest = function (client) {
client.getAttribute("#main ul li a.first", "href", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, "#home");
});
};
.getCookie()
Retrieve a single cookie visible to the current page. The cookie is returned as a cookie JSON object, as defined here.
Uses cookie protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
name |
string | The cookie name. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| object|null | The cookie object as a selenium cookie JSON object or null if the cookie wasn't found. |
Usage:
this.demoTest = function(browser) {
browser.getCookie(name, function callback(result) {
this.assert.equal(result.value, '123456');
this.assert.equals(result.name, 'test_cookie');
});
}
.getCookies()
Retrieve all cookies visible to the current page. The cookies are returned as an array of cookie JSON object, as defined here.
Uses cookie protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | The callback function which will receive the response as an argument. |
Returns
| Type | description |
|---|---|
| Array.<object> | A list of cookies. |
Usage:
this.demoTest = function(browser) {
browser.getCookies(function callback(result) {
this.assert.equal(result.value.length, 1);
this.assert.equals(result.value[0].name, 'test_cookie');
});
}
.getCssProperty()
Retrieve the value of a css property for a given DOM element. Uses elementIdCssProperty protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
cssProperty |
string | The CSS property to inspect. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| * | The value of the css property |
Usage:
this.demoTest = function (client) {
client.getCssProperty("#main ul li a.first", "display", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, 'inline');
});
};
.getElementSize()
Determine an element's size in pixels. Uses elementIdSize protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| {width: number, height: number} | The width and height of the element in pixels |
Usage:
this.demoTest = function (client) {
client.getElementSize("#main ul li a.first", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value.width, 500);
this.assert.equal(result.value.height, 20);
});
};
.getLocation()
Determine an element's location on the page. The point (0, 0) refers to the upper-left corner of the page.
The element's coordinates are returned as a JSON object with x and y properties. Uses elementIdLocation protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| x:number, y:number | The X and Y coordinates for the element on the page. |
Usage:
this.demoTest = function (client) {
client.getLocation("#main ul li a.first", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value.x, 200);
this.assert.equal(result.value.y, 200);
});
};
.getLocationInView()
Determine an element's location on the screen once it has been scrolled into view. Uses elementIdLocationInView protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| x: number, y: number | The X and Y coordinates for the element on the page. |
Usage:
this.demoTest = function (browser) {
browser.getLocationInView("#main ul li a.first", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value.x, 200);
this.assert.equal(result.value.y, 200);
});
};
.getLog()
Gets a log from selenium.
Parameters:
| Name | Type | description |
|---|---|---|
typeString |
string|function | Log type to request |
callback |
function | Callback function which is called with the result value. |
Usage:
this.demoTest = function(client) {
this.getLog('browser', function(logEntriesArray) {
console.log('Log length: ' + logEntriesArray.length);
logEntriesArray.forEach(function(log) {
console.log('[' + log.level + '] ' + log.timestamp + ' : ' + log.message);
});
});
};
.getLogTypes()
Gets the available log types. More info about log types in WebDriver can be found here: https://github.com/SeleniumHQ/selenium/wiki/Logging
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| Array | Available log types |
Usage:
this.demoTest = function(client) {
this.getLogTypes(function(typesArray) {
console.log(typesArray);
});
};
.getTagName()
Query for an element's tag name. Uses elementIdName protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| number | The element's tag name, as a lowercase string. |
Usage:
this.demoTest = function (client) {
client.getTagName("#main ul li .first", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, "a");
});
};
.getText()
Returns the visible text for the element. Uses elementIdText protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| string | The element's visible text. |
Usage:
this.demoTest = function (browser) {
browser.getText("#main ul li a.first", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, "nightwatchjs.org");
});
};
.getTitle()
Returns the title of the current page. Uses title protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| string | The page title. |
Usage:
this.demoTest = function (browser) {
browser.getTitle(function(title) {
this.assert.equal(typeof title, 'string');
this.assert.equal(title, 'Nightwatch.js');
});
};
.getValue()
Returns a form element current value. Uses elementIdValue protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| string | The element's value. |
Usage:
this.demoTest = function (browser) {
browser.getValue("form.login input[type=text]", function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, "enter username");
});
};
.init()
This command is an alias to url and also a convenience method when called without any arguments in the sense that it performs a call to .url() with passing the value of launch_url field from the settings file.
Uses url protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
urlOptional |
string | Url to navigate to. |
Usage:
this.demoTest = function (client) {
client.init();
};
.injectScript()
Utility command to load an external script into the page specified by url.
Parameters:
| Name | Type | description |
|---|---|---|
scriptUrl |
string | The script file url |
idOptional |
string | Dom element id to be set on the script tag. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Returns
| Type | description |
|---|---|
| HTMLScriptElement | The newly created script tag. |
Usage:
this.demoTest = function(client) {
this.injectScript("{script-url}", function() {
// we're all done here.
});
};
.isLogAvailable()
Utility command to test if the log type is available.
Parameters:
| Name | Type | description |
|---|---|---|
typeString |
string|function | Type of log to test |
callback |
function | Callback function which is called with the result value. |
Usage:
this.demoTest = function(browser) {
browser.isLogAvailable('browser', function(isAvailable) {
// do something more in here
});
}
.isVisible()
Determine if an element is currently displayed. Uses elementIdDisplayed protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callback |
function | Callback function which is called with the result value. |
Usage:
this.demoTest = function (browser) {
browser.isVisible('#main', function(result) {
this.assert.equal(typeof result, "object");
this.assert.equal(result.status, 0);
this.assert.equal(result.value, true);
});
};
.maximizeWindow()
Maximizes the current window.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.maximizeWindow();
};
.moveToElement()
Move the mouse by an offset of the specified element. Uses moveTo protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
xoffset |
number | X offset to move to, relative to the top-left corner of the element. |
yoffset |
number | Y offset to move to, relative to the top-left corner of the element. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.moveToElement('#main', 10, 10);
};
.pause()
Suspends the test for the given time in milliseconds. If the milliseconds argument is missing it will suspend the test indefinitely
Parameters:
| Name | Type | description |
|---|---|---|
ms |
number | The number of milliseconds to wait. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.pause(1000);
// or suspend indefinitely
browser.pause();
};
.perform()
A simple perform command which allows access to the "api" in a callback.
Can be useful if you want to read variables set by other commands.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | The function to run as part of the queue. Its signature can have up to two parameters. No parameters: callback runs and perform completes immediately at the end of the execution of the callback. One parameter: allows for asynchronous execution within the callback providing a done callback function for completion as the first argument. Two parameters: allows for asynchronous execution with the "api" object passed in as the first argument, followed by the done callback. |
Usage:
this.demoTest = function (browser) {
var elementValue;
browser
.getValue('.some-element', function(result) {
elementValue = result.value;
})
// other stuff going on ...
//
// self-completing callback
.perform(function() {
console.log('elementValue', elementValue);
// without any defined parameters, perform
// completes immediately (synchronously)
})
//
// asynchronous completion
.perform(function(done) {
console.log('elementValue', elementValue);
// potentially other async stuff going on
// on finished, call the done callback
done();
})
//
// asynchronous completion including api (client)
.perform(function(client, done) {
console.log('elementValue', elementValue);
// similar to before, but now with client
// potentially other async stuff going on
// on finished, call the done callback
done();
});
};
.resizeWindow()
Resizes the current window.
Parameters:
| Name | Type | description |
|---|---|---|
width |
number | The new window width. |
height |
number | The new window height. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.resizeWindow(1000, 800);
};
.saveScreenshot()
Take a screenshot of the current page and saves it as the given filename.
Parameters:
| Name | Type | description |
|---|---|---|
fileName |
string | The complete path to the file name where the screenshot should be saved. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.saveScreenshot('/path/to/fileName.png');
};
.setCookie()
Set a cookie, specified as a cookie JSON object, as defined here.
Uses cookie protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
cookie |
object | The cookie object. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function(browser) {
browser.setCookie({
name : "test_cookie",
value : "test_value",
path : "/", (Optional)
domain : "example.org", (Optional)
secure : false, (Optional)
httpOnly : false, // (Optional)
expiry : 1395002765 // (Optional) time in seconds since midnight, January 1, 1970 UTC
});
}
.setValue()
See sessionsessionidelementidvalue
Sends some text to an element. Can be used to set the value of a form element or to send a sequence of key strokes to an element. Any UTF-8 character may be specified.
An object map with available keys and their respective UTF-8 characters, as defined on W3C WebDriver draft spec, is loaded onto the main Nightwatch instance as client.Keys.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
inputValue |
string|array | The text to send to the element or key strokes. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
// send some simple text to an input
this.demoTest = function (browser) {
browser.setValue('input[type=text]', 'nightwatch');
};
//
// send some text to an input and hit enter.
this.demoTest = function (browser) {
browser.setValue('input[type=text]', ['nightwatch', browser.Keys.ENTER]);
};
.setWindowPosition()
Sets the current window position.
Parameters:
| Name | Type | description |
|---|---|---|
offsetX |
number | The new window offset x-position. |
offsetY |
number | The new window offset y-position. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.setWindowPosition(0, 0);
};
.submitForm()
Submit a FORM element. The submit command may also be applied to any element that is a descendant of a FORM element. Uses submit protocol command.
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The CSS/Xpath selector used to locate the element. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.submitForm('form.login');
};
.switchWindow()
Change focus to another window. The window to change focus to may be specified by its server assigned window handle, or by the value of its name attribute.
To find out the window handle use window_handles protocol action
Parameters:
| Name | Type | description |
|---|---|---|
handleOrName |
string | The server assigned window handle or the name attribute. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.window_handles(function(result) {
var handle = result.value[0];
browser.switchWindow(handle);
});
};
.urlHash()
Convenience method that adds the specified hash (i.e. url fragment) to the current value of the launch_url as set in nightwatch.json.
Parameters:
| Name | Type | description |
|---|---|---|
hash |
string | The hash to add/replace to the current url (i.e. the value set in the launch_url property in nightwatch.json). |
Usage:
this.demoTest = function (client) {
client.urlHash('#hashvalue');
// or
client.urlHash('hashvalue');
};
.useCss()
Sets the locate strategy for selectors to css selector, therefore every following selector needs to be specified as css.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser
.useCss() // we're back to CSS now
.setValue('input[type=text]', 'nightwatch');
};
.useXpath()
Sets the locate strategy for selectors to xpath, therefore every following selector needs to be specified as xpath.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser
.useXpath() // every selector now must be xpath
.click("//tr[@data-recordid]/span[text()='Search Text']");
};
.waitForElementNotPresent()
Opposite of waitForElementPresent. Waits a given time in milliseconds for an element to be not present (i.e. removed) in the page before performing any other commands or assertions.
If the element is still present after the specified amount of time, the test fails.
You can change the polling interval by defining a waitForConditionPollInterval property (in milliseconds) in as a global property in your nightwatch.json or in your external globals file.
Similarly, a default timeout can be specified as a global waitForConditionTimeout property (in milliseconds).
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The selector (CSS / Xpath) used to locate the element. |
time |
number | The number of milliseconds to wait. The runner performs repeated checks every 500 ms. |
abortOnFailureOptional |
boolean | By the default if the element is not found the test will fail. Set this to false if you wish for the test to continue even if the assertion fails. To set this globally you can define a property `abortOnAssertionFailure` in your globals. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
messageOptional |
string | Optional message to be shown in the output; the message supports two placeholders: %s for current selector and %d for the time (e.g. Element %s was not in the page for %d ms). |
Usage:
this.demoTest = function (browser) {
browser.waitForElementNotPresent('#dialog', 1000);
};
.waitForElementNotVisible()
Opposite of waitForElementVisible. Waits a given time in milliseconds for an element to be not visible (i.e. hidden but existing) in the page before performing any other commands or assertions.
If the element fails to be hidden in the specified amount of time, the test fails.
You can change the polling interval by defining a waitForConditionPollInterval property (in milliseconds) in as a global property in your nightwatch.json or in your external globals file.
Similarly, a default timeout can be specified as a global waitForConditionTimeout property (in milliseconds).
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The selector (CSS / Xpath) used to locate the element. |
time |
number | The number of milliseconds to wait. The runner performs repeated checks every 500 ms. |
abortOnFailureOptional |
boolean | By the default if the element is not found the test will fail. Set this to false if you wish for the test to continue even if the assertion fails. To set this globally you can define a property `abortOnAssertionFailure` in your globals. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
messageOptional |
string | Optional message to be shown in the output; the message supports two placeholders: %s for current selector and %d for the time (e.g. Element %s was not in the page for %d ms). |
Usage:
this.demoTest = function (browser) {
browser.waitForElementNotVisible('#dialog', 1000);
};
.waitForElementPresent()
Waits a given time in milliseconds for an element to be present in the page before performing any other commands or assertions.
If the element fails to be present in the specified amount of time, the test fails. You can change this by setting abortOnFailure to false.
You can change the polling interval by defining a waitForConditionPollInterval property (in milliseconds) in as a global property in your nightwatch.json or in your external globals file.
Similarly, a default timeout can be specified as a global waitForConditionTimeout property (in milliseconds).
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The selector (CSS / Xpath) used to locate the element. |
time |
number | The number of milliseconds to wait. The runner performs repeated checks every 500 ms. |
abortOnFailureOptional |
boolean | By the default if the element is not found the test will fail. Set this to false if you wish for the test to continue even if the assertion fails. To set this globally you can define a property `abortOnAssertionFailure` in your globals. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
messageOptional |
string | Optional message to be shown in the output; the message supports two placeholders: %s for current selector and %d for the time (e.g. Element %s was not in the page for %d ms). |
Usage:
this.demoTest = function (browser) {
browser.waitForElementPresent('body', 1000);
// continue if failed
browser.waitForElementPresent('body', 1000, false);
// with callback
browser.waitForElementPresent('body', 1000, function() {
// do something while we're here
});
// custom Spanish message
browser.waitForElementPresent('body', 1000, 'elemento %s no era presente en %d ms');
// many combinations possible - the message is always the last argument
browser.waitForElementPresent('body', 1000, false, function() {}, 'elemento %s no era presente en %d ms');
};
.waitForElementVisible()
Waits a given time in milliseconds for an element to be visible in the page before performing any other commands or assertions.
If the element fails to be present and visible in the specified amount of time, the test fails. You can change this by setting abortOnFailure to false.
You can change the polling interval by defining a waitForConditionPollInterval property (in milliseconds) in as a global property in your nightwatch.json or in your external globals file.
Similarly, a default timeout can be specified as a global waitForConditionTimeout property (in milliseconds).
Parameters:
| Name | Type | description |
|---|---|---|
selector |
string | The selector (CSS / Xpath) used to locate the element. |
time |
number | The number of milliseconds to wait. The runner performs repeated checks every 500 ms. |
abortOnFailureOptional |
boolean | By the default if the element is not found the test will fail. Set this to false if you wish for the test to continue even if the assertion fails. To set this globally you can define a property `abortOnAssertionFailure` in your globals. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
messageOptional |
string | Optional message to be shown in the output; the message supports two placeholders: %s for current selector and %d for the time (e.g. Element %s was not in the page for %d ms). |
Usage:
this.demoTest = function (browser) {
browser.waitForElementVisible('body', 1000);
// continue if failed
browser.waitForElementVisible('body', 1000, false);
// with callback
browser.waitForElementVisible('body', 1000, function() {
// do something while we're here
});
// custom Spanish message
browser.waitForElementVisible('body', 1000, 'elemento %s no era visible en %d ms');
// many combinations possible - the message is always the last argument
browser.waitForElementVisible('body', 1000, false, function() {}, 'elemento %s no era visible en %d ms');
};
WebDriver Protocol
The protocol commands are most of the times simple mappings to the Selenium JsonWireProtocol endpoints.
Some of them are basic commands (such as url and execute) and others are internal commands being used by Nightwatch commands and assertions.
Sessions
A WebDriver session represents the connection between a local end and a specific remote end. Read more on WebDriver page.
.session()
Get info about, delete or create a new session. Defaults to the current session.
Parameters:
| Name | Type | description |
|---|---|---|
actionOptional |
string | The http verb to use, can be "get", "post" or "delete". If only the callback is passed, get is assumed by default. |
sessionIdOptional |
string | The id of the session to get info about or delete. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Usage:
this.demoTest = function (browser) {
browser.session(function(result) {
console.log(result.value);
});
//
browser.session('delete', function(result) {
console.log(result.value);
});
//
browser.session('delete', '12345-abc', function(result) {
console.log(result.value);
});
};
.sessions()
Returns a list of the currently active sessions.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Usage:
this.demoTest = function (browser) {
browser.sessions(function(result) {
console.log(result.value);
});
};
.timeouts()
Configure the amount of time that a particular type of operation can execute for before they are aborted and a |Timeout| error is returned to the client.
Parameters:
| Name | Type | description |
|---|---|---|
type |
string | The type of operation to set the timeout for. Valid values are: "script" for script timeouts, "implicit" for modifying the implicit wait timeout and "page load" for setting a page load timeout. |
ms |
number | The amount of time, in milliseconds, that time-limited commands are permitted to run. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.timeoutsAsyncScript()
Set the amount of time, in milliseconds, that asynchronous scripts executed by .executeAsync are permitted to run before they are aborted and a |Timeout| error is returned to the client.
Parameters:
| Name | Type | description |
|---|---|---|
ms |
number | The amount of time, in milliseconds, that time-limited commands are permitted to run. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.timeoutsImplicitWait()
Set the amount of time the driver should wait when searching for elements. If this command is never sent, the driver will default to an implicit wait of 0ms.
Parameters:
| Name | Type | description |
|---|---|---|
ms |
number | The amount of time, in milliseconds, that time-limited commands are permitted to run. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.status()
Query the server's current status.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
.sessionLog()
Gets the text of the log type specified. To find out the available log types, use .getLogTypes().
Parameters:
| Name | Type | description |
|---|---|---|
typeString |
string | Type of log to request. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| Array | Array of the text entries of the log. |
.sessionLogTypes()
Gets an array of strings for which log types are available. This methods returns the entire WebDriver response, if you are only interested in the logs array, use .getLogTypes() instead.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Navigation
The commands in this section allow navigation to new URLs and introspection of the currently loaded url.
.url()
Retrieve the URL of the current page or navigate to a new URL.
Parameters:
| Name | Type | description |
|---|---|---|
urlOptional |
string|function | If missing, it will return the URL of the current page as an argument to the supplied callback. |
callbackOptional |
Function |
Usage:
module.exports = {
'demo Test' : function(browser) {
browser.url(function(result) {
// return the current url
console.log(result);
});
//
// navigate to new url:
browser.url('{URL}');
//
//
// navigate to new url:
browser.url('{URL}', function(result) {
console.log(result);
});
}
};
.back()
Navigate backwards in the browser history, if possible.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.forward()
Navigate forwards in the browser history, if possible.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.refresh()
Refresh the current page.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.title()
Get the current page title.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Command Contexts
.window()
Change focus to another window or close the current window. Shouldn't normally be used directly, instead .switchWindow() and .closeWindow() should be used.
Parameters:
| Name | Type | description |
|---|---|---|
method |
string | The HTTP method to use. Can be either `POST` (change focus) or `DELETE` (close window). |
handleOrName |
string | The window to change focus to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.windowHandle()
Retrieve the current window handle.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
.windowHandles()
Retrieve the list of all window handles available to the session.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
.windowMaximize()
Increases the window to the maximum available size without going full-screen.
Parameters:
| Name | Type | description |
|---|---|---|
handleOrNameOptional |
string | windowHandle URL parameter; if it is "current", the currently active window will be maximized. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.windowPosition()
Change or get the position of the specified window. If the second argument is a function it will be used as a callback and the call will perform a get request to retrieve the existing window position.
Parameters:
| Name | Type | description |
|---|---|---|
windowHandle |
string | |
offsetX |
number | |
offsetY |
number | |
callback |
function | Callback function which is called with the result value. |
.windowSize()
Change or get the size of the specified window. If the second argument is a function it will be used as a callback and the call will perform a get request to retrieve the existing window size.
Parameters:
| Name | Type | description |
|---|---|---|
windowHandle |
string | |
width |
number | |
height |
number | |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.frame()
Change focus to another frame on the page. If the frame id is missing or null, the server should switch to the page's default content.
Parameters:
| Name | Type | description |
|---|---|---|
frameIdOptional |
string|number|null | Identifier for the frame to change focus to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.frameParent()
Change focus to the parent context. If the current context is the top level browsing context, the context remains unchanged.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Elements
These are the low level commands that are used to locate elements in the page. Each element has an associated web element reference (a UUID) that uniquely identifies the element across all browsing contexts. More details on elements are available on the WebDriver page.
Details on how WebDriver checks if the element is displayed are available Element Displayedness page.
.element()
Search for an element on the page, starting from the document root. The located element will be returned as a WebElement JSON object.
First argument to be passed is the locator strategy, which is detailed on the WebDriver docs.
Parameters:
| Name | Type | description |
|---|---|---|
using |
string | The locator strategy to use. |
value |
string | The search target. |
callback |
function | Callback function which is called with the result value. |
Usage:
module.exports = {
'demo Test' : function(browser) {
browser.element('css selector', 'body', function(res) {
console.log(res)
});
}
};
.elements()
Search for multiple elements on the page, starting from the document root. The located elements will be returned as WebElement JSON objects.
First argument to be passed is the locator strategy, which is detailed on the WebDriver docs.
Parameters:
| Name | Type | description |
|---|---|---|
using |
string | The locator strategy to use. |
value |
string | The search target. |
callback |
function | Callback function to be invoked with the result when the command finishes. |
.elementIdElement()
Search for an element on the page, starting from the identified element. The located element will be returned as a WebElement JSON object.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
using |
string | The locator strategy to use. |
value |
string | The search target. |
callback |
function | Callback function which is called with the result value. |
.elementIdElements()
Search for multiple elements on the page, starting from the identified element. The located element will be returned as a WebElement JSON objects.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
using |
string | The locator strategy to use. |
value |
string | The search target. |
callback |
function | Callback function which is called with the result value. |
.elementIdEquals()
Test if two element IDs refer to the same DOM element.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
otherId |
string | ID of the element to compare against. |
callback |
function | Callback function which is called with the result value. |
.elementActive()
Get the element on the page that currently has focus.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Element State
.elementIdAttribute()
Get the value of an element's attribute.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
attributeName |
string | The attribute name |
callback |
function | Callback function which is called with the result value. |
.elementIdCssProperty()
Retrieve the computed value of the given CSS property of the given element.
The CSS property to query should be specified using the CSS property name, not the JavaScript property name (e.g. background-color instead of backgroundColor).
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
cssPropertyName |
string | |
callback |
function | Callback function which is called with the result value. |
.elementIdDisplayed()
Determine if an element is currently displayed.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
.elementIdEnabled()
Determine if an element is currently enabled.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
.elementIdName()
Retrieve the qualified tag name of the given element.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
.elementIdSelected()
Determine if an OPTION element, or an INPUT element of type checkbox or radio button is currently selected.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
.elementIdSize()
Determine an element's size in pixels. The size will be returned as a JSON object with width and height properties.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
.elementIdText()
Returns the visible text for the element.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
Element Interaction
.elementIdClear()
Scrolls into view a submittable element excluding buttons or editable element, and then attempts to clear its value, reset the checked state, or text content.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.elementIdClick()
Scrolls into view the element and clicks the in-view centre point. If the element is not pointer-interactable, an element not interactable error is returned.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.elementIdValue()
Scrolls into view the form control element and then sends the provided keys to the element, or returns the current value of the element. In case the element is not keyboard interactable, an element not interactable error is returned.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
valueOptional |
string|array|none | Value to send to element in case of a POST |
callback |
function | Callback function which is called with the result value. |
.keys()
Send a sequence of key strokes to the active element. The sequence is defined in the same format as the sendKeys command.
An object map with available keys and their respective UTF-8 characters, as defined on W3C WebDriver draft spec, is loaded onto the main Nightwatch instance as client.Keys.
Rather than the setValue, the modifiers are not released at the end of the call. The state of the modifier keys is kept between calls, so mouse interactions can be performed while modifier keys are depressed.
Parameters:
| Name | Type | description |
|---|---|---|
keysToSend |
Array | The keys sequence to be sent. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.submit()
Submit a FORM element. The submit command may also be applied to any element that is a descendant of a FORM element.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Element Location
.elementIdLocationInView()
Determine an element's location on the screen once it has been scrolled into view.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.elementIdLocation()
Determine an element's location on the page. The point (0, 0) refers to the upper-left corner of the page.
The element's coordinates are returned as a JSON object with x and y properties.
Parameters:
| Name | Type | description |
|---|---|---|
id |
string | ID of the element to route the command to. |
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| x:number, y:number | The X and Y coordinates for the element on the page. |
Document Handling
.source()
Returns a string serialisation of the DOM of the current page.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
.execute()
Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. The executed script is assumed to be synchronous and the result of evaluating the script is returned to the client.
The script argument defines the script to execute in the form of a function body. The value returned by that function will be returned to the client.
The function will be invoked with the provided args array and the values may be accessed via the arguments object in the order specified.
Parameters:
| Name | Type | description |
|---|---|---|
body |
string|function | The function body to be injected. |
args |
Array | An array of arguments which will be passed to the function. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Returns
| Type | description |
|---|---|
| * | The script result. |
Usage:
this.demoTest = function (browser) {
browser.execute(function(data) {
// resize operation
return true;
}, [imagedata], function(result) {
...
});
};
.executeAsync()
Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame. The executed script is assumed to be asynchronous and the result of evaluating the script is returned to the client.
Asynchronous script commands may not span page loads. If an unload event is fired while waiting for a script result, an error should be returned to the client.
Parameters:
| Name | Type | description |
|---|---|---|
script |
string|function | The function body to be injected. |
args |
Array | An array of arguments which will be passed to the function. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Returns
| Type | description |
|---|---|
| * | The script result. |
Usage:
this.demoTest = function (browser) {
browser.executeAsync(function(data, done) {
someAsyncOperation(function() {
done(true);
});
}, [imagedata], function(result) {
// ...
});
};
Cookies
.cookie()
Retrieve or delete all cookies visible to the current page or set a cookie. Normally this shouldn't be used directly, instead the cookie convenience methods should be used: getCookie, getCookies, setCookie, deleteCookie, deleteCookies.
Parameters:
| Name | Type | description |
|---|---|---|
method |
string | Http method |
callbackOrCookieOptional |
function|object | Optional callback function to be called when the command finishes. |
User Actions
.doubleClick()
Double-clicks at the current mouse coordinates (set by .moveto()).
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.mouseButtonClick()
Click at the current mouse coordinates (set by moveto).
The button can be (0, 1, 2) or ('left', 'middle', 'right'). It defaults to left mouse button, and if you don't pass in a button but do pass in a callback, it will handle it correctly.
Parameters:
| Name | Type | description |
|---|---|---|
button |
string|number | The mouse button |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.mouseButtonDown()
Click and hold the left mouse button (at the coordinates set by the last moveto command). Note that the next mouse-related command that should follow is mouseButtonUp . Any other mouse command (such as click or another call to buttondown) will yield undefined behaviour.
Can be used for implementing drag-and-drop. The button can be (0, 1, 2) or ('left', 'middle', 'right'). It defaults to left mouse button, and if you don't pass in a button but do pass in a callback, it will handle it correctly.
Parameters:
| Name | Type | description |
|---|---|---|
button |
string|number | The mouse button |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.mouseButtonUp()
Releases the mouse button previously held (where the mouse is currently at). Must be called once for every mouseButtonDown command issued.
Can be used for implementing drag-and-drop. The button can be (0, 1, 2) or ('left', 'middle', 'right'). It defaults to left mouse button, and if you don't pass in a button but do pass in a callback, it will handle it correctly.
Parameters:
| Name | Type | description |
|---|---|---|
button |
string|number | The mouse button |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.moveTo()
Move the mouse by an offset of the specificed element. If no element is specified, the move is relative to the current mouse cursor. If an element is provided but no offset, the mouse will be moved to the center of the element.
If the element is not visible, it will be scrolled into view.
Parameters:
| Name | Type | description |
|---|---|---|
element |
string | Opaque ID assigned to the element to move to. If not specified or is null, the offset is relative to current position of the mouse. |
xoffset |
number | X offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element. |
yoffset |
number | Y offset to move to, relative to the top-left corner of the element. If not specified, the mouse will move to the middle of the element. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
User Prompts
.acceptAlert()
Accepts the currently displayed alert dialog. Usually, this is equivalent to clicking on the 'OK' button in the dialog.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.dismissAlert()
Dismisses the currently displayed alert dialog. For confirm() and prompt() dialogs, this is equivalent to clicking the 'Cancel' button.
For alert() dialogs, this is equivalent to clicking the 'OK' button.
Parameters:
| Name | Type | description |
|---|---|---|
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.getAlertText()
Gets the text of the currently displayed JavaScript alert(), confirm(), or prompt() dialog.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| string | The text of the currently displayed alert. |
.setAlertText()
Sends keystrokes to a JavaScript prompt() dialog.
Parameters:
| Name | Type | description |
|---|---|---|
value |
string | Keystrokes to send to the prompt() dialog |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
Screen Capture
.screenshot()
Take a screenshot of the current page.
Parameters:
| Name | Type | description |
|---|---|---|
log_screenshot_data |
boolean | Whether or not the screenshot data should appear in the logs when running with --verbose |
callback |
function | Callback function which is called with the result value. |
Mobile Related
.getOrientation()
Get the current browser orientation.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function which is called with the result value. |
Returns
| Type | description |
|---|---|
| string} The current browser orientation: {LANDSCAPE|PORTRAIT |
.setOrientation()
Sets the browser orientation.
Parameters:
| Name | Type | description |
|---|---|---|
orientation |
string | The new browser orientation: {LANDSCAPE|PORTRAIT} |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
.contexts()
Get a list of the available contexts.
Used by Appium when testing hybrid mobile web apps. More info here: https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/hybrid.md.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function to be called when the command finishes. |
Returns
| Type | description |
|---|---|
| Array | an array of strings representing available contexts, e.g 'WEBVIEW', or 'NATIVE' |
.currentContext()
Get current context.
Parameters:
| Name | Type | description |
|---|---|---|
callback |
function | Callback function to be called when the command finishes. |
Returns
| Type | description |
|---|---|
| string|null | a string representing the current context or `null`, representing "no context" |
.setContext()
Sets the context.
Parameters:
| Name | Type | description |
|---|---|---|
context |
string | context name to switch to - a string representing an available context. |
callbackOptional |
function | Optional callback function to be called when the command finishes. |
v0.9.12