Automated testing with Selenium WebDriver and Node.js

A lifelong learner. Love to travel. Listen to music.
Search for a command to run...

A lifelong learner. Love to travel. Listen to music.
No comments yet. Be the first to comment.
Fork or clone the source code here Multer is a Node.js middleware, used to upload or handle multipart/form-data, on the top of Busboy. Here I’ll explain the basic procedure of uploading a file in Node.js server. Work-Flow First Get the seed code. ...
Best Practices for Path Structure, Versioning, and Error Handling

Understanding the Performance Implications of async and defer Attributes

Overview static: Default position. It does not allow setting properties like top, bottom, left, right, z-index relative: Acts the same as static. but allows positioning it relatively by putting properties like top, bottom, left, right, z-index absolu...

Overview When an element in the browser has a conflict of styles, the browser uses a set of rules to determine which style should be rendered. This set of rules is defined as CSS Selector Specificity. For instance, for an element, if we have the foll...

Master block, inline, flex, and grid to build better web layouts

Source Code

Selenium is an automated open source and cross-platform testing tool. It can be used in all major browsers(Chrome, Firefox, Opera, IE, and Edge) using almost all major programming languages. Also, it can be integrated with various native testing tools and library. In this article, I will explain a test procedure in google search homepage with selenium web-driver and Node.js.
Here we run an automated test on https://www.google.com/ LOL
First, we test if the landing page has an input box and a button to submit.
Then we put a random name to the input box and hit submit. We will check if the search results appear.
All these activities will be taken care of by our selenium web-driver.
For the testing framework, we are using mocha, and we include chai assertion library with it.
**Clone or fork the repo for further changes**
Our project will follow the following structure.
├── ...
│
├── lib # Helper methods
│ ├── basePage.js # Generic functionality for tests
│ └── homePage.js # Home page testing functionality
│
├── test # Test suite
│ └── homePage.test.js # Testing in home page
│
├── utils # Utility files for testing
│ ├── fakeData.js # Generating random keyword for searching
│ └── locator.js # HTML and CSS identifier for elements to test
│
├── package.json # Project dependency
├── ...
Your final package.json should look similar like this.
{
"name": "googlesearch",
"version": "1.0.0",
"description": "Google home page automated test ",
"main": "index.js",
"scripts": {
"test": "mocha test --reporter mochawesome --reporter-options autoOpen=true"
},
"repository": {
"type": "git",
"url": "git+https://github.com/bmshamsnahid/Automation-With-Selenium-And-Node.js.git"
},
"author": "B M Shams Nahid",
"license": "ISC",
"bugs": {
"url": "https://github.com/bmshamsnahid/Automation-With-Selenium-And-Node.js/issues"
},
"homepage": "https://github.com/bmshamsnahid/Automation-With-Selenium-And-Node.js#readme",
"devDependencies": {
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chromedriver": "^2.41.0",
"faker": "^4.1.0",
"mocha": "^5.2.0",
"mochawesome": "^3.0.3",
"selenium-webdriver": "^4.0.0-alpha.1"
}
}
We have 2 utility methods in out util directory.
fakeData.js
locator.js
In utils/fakeData.js, We generate the random name to search in the google.
const faker = require('faker');
module.exports = {
nameKeyword: faker.name.findName()
};
In utils/locator.js we put the HTML elements selector to manipulate.
module.exports = {
searchInputSelectorId: 'lst-ib',
searchButtonSelectorName: 'btnK',
resultConfirmationId: 'resultStats'
};
Here are the three selectors.
Google search input box as “searchInputSelectorId”,
Google search button key as “searchButtonSelectorName”
No of search results found on the result page as “resultStats”
We put our generic methods in lib/basePage.js
*Code reference Quit Driver Get Url Find Element Find By Id Fill Input*
const {Builder, By, until} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
let o = new chrome.Options();
// o.addArguments('start-fullscreen');
o.addArguments('disable-infobars');
// o.addArguments('headless'); // running test on visual chrome browser
o.setUserPreferences({ credential_enable_service: false });
var Page = function() {
this.driver = new Builder()
.setChromeOptions(o)
.forBrowser('chrome')
.build();
// visit a webpage
this.visit = async function(theUrl) {
return await this.driver.get(theUrl);
};
// quit current session
this.quit = async function() {
return await this.driver.quit();
};
// wait and find a specific element with it's id
this.findById = async function(id) {
await this.driver.wait(until.elementLocated(By.id(id)), 15000, 'Looking for element');
return await this.driver.findElement(By.id(id));
};
// wait and find a specific element with it's name
this.findByName = async function(name) {
await this.driver.wait(until.elementLocated(By.name(name)), 15000, 'Looking for element');
return await this.driver.findElement(By.name(name));
};
// fill input web elements
this.write = async function (el, txt) {
return await el.sendKeys(txt);
};
};
module.exports = Page;
For test purpose, page specific methods are put in the utils/homePage.js
let Page = require('./basePage');
const locator = require('../utils/locator');
const fake = require('../utils/fakeData');
const searchInputSelectorId = locator.searchInputSelectorId;
const searchButtonSelectorName = locator.searchButtonSelectorName;
const resultConfirmationSelectorId = locator.resultConfirmationId;
const fakeNameKeyword = fake.nameKeyword;
let searchInput, searchButton, resultStat;
Page.prototype.findInputAndButton = async function () {
searchInput = await this.findById(searchInputSelectorId);
searchButton = await this.findByName(searchButtonSelectorName);
const result = await this.driver.wait(async function () {
const searchButtonText = await searchButton.getAttribute('value');
const searchInputEnableFlag = await searchInput.isEnabled();
return {
inputEnabled: searchInputEnableFlag,
buttonText: searchButtonText
}
}, 5000);
return result;
};
Page.prototype.submitKeywordAndGetResult = async function() {
await this.findInputAndButton();
await this.write(searchInput, fakeNameKeyword);
await searchButton.click();
resultStat = await this.findById(resultConfirmationSelectorId);
return await this.driver.wait(async function () {
return await resultStat.getText();
}, 5000);
};
module.exports = Page;
We have two methods here.
The first method finds the button and input box. Check its availability.
The second method put a random name(grabbed from the faker.js) in the input box and confirm the search results found.
Time to create our first test suite in test/homePage.test.js
const { describe, it, after, before } = require('mocha');
const Page = require('../lib/homePage');
const chai = require('chai');
const expect = chai.expect;
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
process.on('unhandledRejection', () => {});
(async function example() {
try {
describe ('Google search automated testing', async function () {
this.timeout(50000);
let driver, page;
beforeEach (async () => {
page = new Page();
driver = page.driver;
await page.visit('https://www.google.com/');
});
afterEach (async () => {
await page.quit();
});
it ('find the input box and google search button', async () => {
const result = await page.findInputAndButton();
expect(result.inputEnabled).to.equal(true);
expect(result.buttonText).to.include('Google');
});
it ('put keyword in search box and click search button', async () => {
const result = await page.submitKeywordAndGetResult();
expect(result.length).to.be.above(10);
});
});
} catch (ex) {
console.log (new Error(ex.message));
} finally {
}
})();
Here we are running two tests, one for checking the existing of the input box and search button.
Another for checking the search results, after we put our desired key in the search box and hit the search button.
We are ready to perform our first test. Make sure in your package.json file, the test script is written properly. For confirmation, you can check my package.json file. I shared above of the post.
Run
npm test
Now the test will run and both of them should pass.
In order to run the test in the headless browser, go to lib/basePage.js and uncomment the ‘headless’ option for chrome.
In case you want to use Firefox, IE, Edge or Opera browser check the documentation.
Stay tuned and if there is a confusing term or something, response below. I will replay ASAP.