Night Watch Notes
Night Watch Notes
framework that never fails to take the spotlight and that is NightwatchJS.
Nightwatch.js is an open-source automated testing framework that is powered by
Node.js and provides complete E2E (end to end) solutions to automation testing with
Selenium Javascript be it for web apps, browser apps, and websites.
This NightwatchJS tutorial will help you explore its advantages and how it can be
installed for flawless automation testing.
Table of Contents
Advantages of Nightwatch.js
Has a robust configuration and a lightweight framework
Can be easily integrated with cloud service providers like Browserstack for web
and mobile application testing
Low code maintenance
Improves the test structure
Better performance
Allows configuration with Cucumber to build a BDD (Behaviour Driven
Development) setup.
How does Nightwatch.js work?
In order to establish the communication and relay requests, Nightwatch.js employs a
restful HTTP API with the help of an HTTP protocol laid down by the W3C WebDriver
API and extracted from the JSONWire protocol. It communicates over a restful HTTP
API by utilizing the HTTP protocol that is defined by W3C WebDriver API and derived
from the JSONWire protocol.
Nightwatch.js issues dual requests to the WebDriver server in order to carry out any
kind of browser interaction. This request can be issued with the help of a command, an
assertion, or an action that is available on page objects of the web application.
The first request is sent to the Selenium server, for creating a session with the
browser. It locates the target element on which the action has to be performed,
with the help of CSS or XPath selector of that object.
Once, npm is installed, run the below command to install Nightwatch and save it as a
dev dependency.
$ npm install nightwatch --save-dev
"name": "demotest",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "nightwatch"
},
"author": "",
"license": "ISC",
"devDependencies": {
"chromedriver": "^101.0.0",
"nightwatch": "^2.1.4"
module.exports = {
test_settings: {
default: {
webdriver: {
start_process: true,
server_path: chromedriver.path,
port: 4444,
cli_args: ['--port=4444']
},
desiredCapabilities: {
browserName: 'chrome'
};
module.exports = {
browser
.url('https://www.google.com')
.waitForElementVisible('body', 1000)
.setValue('input[type=text]', 'nightwatch')
.waitForElementVisible('input[name=btnK]', 1000)
},
browser
.click('input[name=btnK]')
.pause(1000)
.end(); //to close the browser session after all the steps
On running this command, it picks the value “nightwatch” from “test” key in
package.json file that further hits the nightwatch api to trigger the URL in chromedriver.
Also, there can be one or more than one step in demo.js(step definition js) file as per
the requirement of the test cases.
It is also a good practice to maintain a separate .js file for page objects which consists
of the locator strategy and selectors of the UI elements.
pageObjects.js
module.exports = {
elements: {
googleInputBox: '//input[@type="text"]',
searchButton: '(//input[@value="Google Search"])[2]',
headingText: `//h3[contains(text(),'Nightwatch.js')]`
The locator strategy is set to CSS and Xpath to inspect the UI elements.
async_function.sh
locateStrategy: async function (selector) { return await
selector.startsWith('/') ? 'xpath' : 'css selector'; }
module.exports = {
test_settings: {
default: {
webdriver: {
start_process: true,
server_path: chromedriver.path,
port: 4444,
cli_args: ['--port=4444']
},
desiredCapabilities: {
browserName: 'chrome'
}
};
The below package.json can be used next for the test settings and dependencies.
package.json
{
"name": "nightwatchdemo",
"version": "1.0.0",
"main": "google.js",
"scripts": {
"test": "nightwatch",
},
"author": "",
"license": "ISC",
"dependencies": {
"cucumber": "^5.1.0",
"cucumber-pretty": "^1.5.0"
},
"devDependencies": {
"chromedriver": "^2.40.0",
"nightwatch": "^2.1.4",
"nightwatch-api": "^2.2.0"
module.exports = {
test_settings: {
default: {
webdriver: {
start_process: true,
server_path: chromedriver.path,
port: 4444,
},
desiredCapabilities: {
browserName: 'chrome'
};
The next step is to create a file cucumber.conf.js in the root folder that has the setup of
starting and closing the webdriver sessions.
cucumber.conf.js
const { setDefaultTimeout, AfterAll, BeforeAll } = require('cucumber');
setDefaultTimeout(60000);
BeforeAll(async () => {
await startWebDriver();
await createSession();
});
AfterAll(async () => {
await closeSession();
await stopWebDriver();
});
Then we create a feature file that has the test scenarios in Given, When, Then format.
google.feature
Feature: Google Search
Scenario: Searching Google
});
return client.assert.title(title);
});
return client.assert.visible('input[name="q"]');
});
},
Now, trigger the following command from the terminal to run the tests
npm_run.js
$ npm run e2e-test
NightwatchJS automates the entire test suite quickly with minimal configuration and is
readable as well as very easy to maintain and update. It also supports parallel testing of
cases which proves to be another time-efficient feature of it. On the other hand,
Nightwatch-Cucumber also is a great module for linking the accessibility of Cucumber.js
with the robust testing framework of Nightwatch.js.
However, to get the best results while automation testing, it is highly recommended to
test on a real device cloud.
Re-Notes:
Configuration
For Windows, you need to create nightwatch.js in the root folder and
write in this file path to runner.js, file which required for start
nightwatch process, by default you need to add to this file
require('./node_modules/nightwatch/bin/runner');
For macOS and Linux this is not required.
"selenium": {
"start_process": true,
"server_path": "./lib/selenium-server-standalone-3.9.1.jar",
"log_path": "./reports",
"host": "127.0.0.1",
"port": 4445,
"cli_args": {
"webdriver.chrome.driver": "./lib/drivers/chromedriver.exe",
"webdriver.gecko.driver": "./lib/drivers/geckodriver.exe",
"webdriver.edge.driver": "./lib/drivers/MicrosoftWebDriver.exe"
}
},
"test_settings": {
"default": {
"launch_url": "http://localhost",
"selenium_port": 4445,
"selenium_host": "localhost",
"silent": true,
"screenshots": {
"enabled": true,
"path": "./reports/screenshots"
},
"desiredCapabilities": {
"browserName": "chrome",
"marionette": true,
"javascriptEnabled": true,
"acceptSslCerts": true
}
},
"chrome": {
"desiredCapabilities": {
"browserName": "chrome"
}
},
"firefox": {
"desiredCapabilities": {
"browserName": "firefox"
}
},
"edge": {
"desiredCapabilities": {
"browserName": "MicrosoftEdge"
}
}
}
}
Here is a brief description of the parameters of the nightwatch.json file:
Sample Test:
module.exports = {
'Bing search test' : function (client) {
client
.url('http://www.bing.com')
.waitForElementVisible('body', 1000)
.assert.title('Bing')
.waitForElementVisible('#sb_form_q', 1000)
.setValue('#sb_form_q', 'nightwatch.js')
.submitForm('#sb_form_q')
.pause(1000)
.assert.containsText('#b_results > li:nth-child(1) > h2',
'Nightwatch.js | Node.js powered End-to-End testing …')
.click('#b_results > li:nth-child(1) > h2')
.assert.title('Nightwatch.js | Node.js powered End-to-End testing
framework')
.end();
}
};
This test:
To run this test, you need to enter a command from root folder:
node nightwatch tests/bing_test.js
If you made all steps properly, you would see that Google Chrome
browser start and test run. In the console you will see such result:
Nightwatch example:
NIGHTWATCH COMMANDS:
Actions
javascript
Copy code
browser.click('#selector');
javascript
Copy code
browser.setValue('#selector', 'value');
javascript
Copy code
browser.clearValue('#selector');
javascript
Copy code
browser.submitForm('#selector');
javascript
Copy code
browser.dragAndDrop('#source', '#destination');
javascript
Copy code
browser.execute(function() {
// custom JavaScript
});
Assertions
javascript
Copy code
browser.assert.elementPresent('#selector');
javascript
Copy code
browser.assert.elementNotPresent('#selector');
javascript
Copy code
browser.assert.visible('#selector');
javascript
Copy code
browser.assert.notVisible('#selector');
javascript
Copy code
browser.assert.containsText('#selector', 'text');
javascript
Copy code
browser.assert.urlContains('value');
javascript
Copy code
browser.assert.title('title');
Elements
javascript
Copy code
browser.element('css selector', '#selector', function(result) {
console.log(result);
});
javascript
Copy code
browser.elements('css selector', '.selectors', function(result) {
console.log(result);
});
javascript
Copy code
browser.getAttribute('#selector', 'attribute', function(result) {
console.log(result.value);
});
javascript
Copy code
browser.getText('#selector', function(result) {
console.log(result.value);
});
Browser
javascript
Copy code
browser.url('http://example.com');
javascript
Copy code
browser.back();
javascript
Copy code
browser.forward();
javascript
Copy code
browser.refresh();
javascript
Copy code
browser.maximizeWindow();
javascript
Copy code
browser.resizeWindow(width, height);
javascript
Copy code
browser.closeWindow();
javascript
Copy code
browser.openNewWindow('tab');
In Nightwatch.js, you can retrieve an attribute or value from an element and assign it to a
variable using asynchronous commands. Here’s how you can do it:
To retrieve an attribute (e.g., href, src, data-attribute) from an element and assign it to a
variable:
javascript
Copy code
let attributeValue;
javascript
Copy code
let textContent;
browser.getText('#elementId', function(result) {
textContent = result.value;
});
Nightwatch.js commands are asynchronous, meaning you'll typically need to handle them using
callbacks, promises, or async/await syntax to ensure that you wait for the result before using the
assigned variable. Here’s an example using async/await:
javascript
Copy code
async function getValueAndLog() {
let attributeValue = await new Promise((resolve) => {
browser.getAttribute('#elementId', 'attributeName', function(result) {
resolve(result.value);
});
});
console.log(attributeValue);
}