React app powered with Selenium.
In this tutorial, we will be creating a sample React application using create-react-app and automate it using Selenium WebDriver, covering varied test cases.
Why selenium?
Selenium WebDriver provides a programming interface to create and execute test cases. It automates our development and every developer must now to write unit test cases for their work to manage their code better.
Prerequisites
- Node.js & NPM (NPM comes with Node.js, you don’t need to install it separately)
- Selenium WebDriver
- Chromedriver & Geckodriver
- Mocha
- Firefox and Chrome browsers.
Let’s code
Let’s straight away jump into development.
Create a project called “react-selenium
” using create-react-app.
$ npx create-react-app react-selenium
$ cd react-selenium
$ npm start
Now, you have your app ready, running in the port 3000. You can access it via http://localhost:3000
We will install the above prerequisites in our app.
$ npm i selenium-webdriver chromedriver geckodriver --save
$ npm i mocha --save-dev
Now in your root directory, create a folder called test
and inside of it, create a file called test.js
. Refer the final source code for reference.
In test.js, add the following code in it.
/**
* Dependency Modules
*/
var assert = require("assert").strict;
var webdriver = require("selenium-webdriver");
require("geckodriver");// Application Server
const serverUri = "http://localhost:3000/#";
const appTitle = "React Selenium App";/**
* Config for Chrome browser
* @type {webdriver}
*/
var browser = new webdriver.Builder()
.usingServer()
.withCapabilities({ browserName: "chrome" })
.build();/**
* Config for Firefox browser (Comment Chrome config when you intent to test in Firefox)
* @type {webdriver}
*/
/*
var browser = new webdriver.Builder()
.usingServer()
.withCapabilities({ browserName: "firefox" })
.build();
*//**
* Function to get the title and resolve it it promise.
* @return {[type]} [description]
*/
function logTitle() {
return new Promise((resolve, reject) => {
browser.getTitle().then(function(title) {
resolve(title);
});
});
}/**
* Sample test case
* To check whether the given value is present in array.
*/
describe("Array", function() {
describe("#indexOf()", function() {
it("should return -1 when the value is not present", function() {
assert.equal([1, 2, 3].indexOf(4), -1);
});
});
});describe("Home Page", function() {
/**
* Test case to load our application and check the title.
*/
it("Should load the home page and get title", function() {
return new Promise((resolve, reject) => {
browser
.get(serverUri)
.then(logTitle)
.then(title => {
assert.strictEqual(title, appTitle);
resolve();
})
.catch(err => reject(err));
});
});/**
* Test case to check whether the given element is loaded.
*/
it("Should check whether the given element is loaded", function() {
return new Promise((resolve, reject) => {
browser
.findElement({ id: "sel-button" })
.then(elem => resolve())
.catch(err => reject(err));
});
});/**
* End of test cases use.
* Closing the browser and exit.
*/
after(function() {
// End of test use this.
browser.quit();
});
});
Quite long right? I will explain part by part in it.
/**
* Dependency Modules
*/
var assert = require("assert").strict;
var webdriver = require("selenium-webdriver");
require("geckodriver");
Add these lines at the top, which are the required dependencies to automate our development. assert
is the default Node.js library so no need to install it. Selenium-WebDriver
is the base driver for selenium to run and geckodriver
is essential to run our test cases in other browsers than chrome.
// Application Server
const serverUri = "http://localhost:3000/#";
const appTitle = "React Selenium App";
We are going to work on two test cases.
First, we are going to load our application using Selenium by providing the required URI, get our app title once our application loads and checking it with the given appTitle value.
Second, we are going to find an element in our application to check whether the given element is loaded, which we are going to add it later in this post.
Visit index.html
file in the public
folder and change the title
value as React Selenium App
.
/**
* Config for Chrome browser
* @type {webdriver}
*/
var browser = new webdriver.Builder()
.usingServer()
.withCapabilities({ browserName: "chrome" })
.build();/**
* Config for Firefox browser (Comment Chrome config when you intent to test in Firefox)
* @type {webdriver}
*/
/*
var browser = new webdriver.Builder()
.usingServer()
.withCapabilities({ browserName: "firefox" })
.build();
*/
It’s time to configure selenium by providing proper inputs like in which browser the test cases should load, what are all the configurations needed etc.
Here first browser config value contains configuration for Chrome browsers and I have commented configurations for Firefox browsers. You can do vice-versa when you are ready to test in Firefox.
/**
* Function to get the title and resolve it it promise.
* @return {[type]} [description]
*/
function logTitle() {
return new Promise((resolve, reject) => {
browser.getTitle().then(function(title) {
resolve(title);
});
});
}
Sample function to get the title of the browser using Selenium-WebDriver inbuilt method called getTitle()
and resolving it using Promise.
/**
* Sample test case
* To check whether the given value is present in array.
*/
describe("Array", function() {
describe("#indexOf()", function() {
it("should return -1 when the value is not present", function() {
assert.equal([1, 2, 3].indexOf(4), -1);
});
});
});
Just a sample test case to make you feel more comfortable. Here we are checking whether value 4 present in the given array [1, 2, 3]. In this case, it will return -1 since it is not present, which is equal to -1 (RHS). So the test case is passed. LHS = RHS.
/**
* Test case to load our application and check the title.
*/
it("Should load the home page and get title", function() {
return new Promise((resolve, reject) => {
browser
.get(serverUri)
.then(logTitle)
.then(title => {
assert.strictEqual(title, appTitle);
resolve();
})
.catch(err => reject(err));
});
});
In this test case, the string given in the it
denotes the name of the test case.
We are returning the Promise object because Mocha handles promise objects efficiently and it will be easy to manage our test cases better.
After, we are first opening our app by providing the serverUri
. After that, we are calling the logTitle
function to get the title of our app and passing the title value to the next callback function.
Using assert.strictEqual
method, we are comparing title(LHS) with appTitle(RHS).
Finally, we are resolving it. If those values don’t match, we are rejecting it.
/**
* Test case to check whether the given element is loaded.
*/
it("Should check whether the given element is loaded", function() {
return new Promise((resolve, reject) => {
browser
.findElement({ id: "sel-button" })
.then(elem => resolve())
.catch(err => reject(err));
});
});
For this second test case, let’s add a button in our App.js file and check whether the button is loaded.
Open App.js
file and add the following code after <p>
tag.
<button id="sel-button">Click me!</button>
browser.findElement
(inbuilt Selenium-WebDriver method) find for the element using the given id sel-button
in our app and we are resolving it when we find the element and rejecting it when we fail to find the element.
/**
* End of test cases use.
* Closing the browser and exit.
*/
after(function() {
// End of test use this.
browser.quit();
});
Finally, after the end of test cases, we are closing the browser and it’s instance.
Run the test-case
Now, we are going to run these test cases. Add the below line (command) in the script object in your package.json file.
"s-test": "mocha test"
It’s time to run. From your root directory, run the following command as follows.
$ npm run s-test
Now you can see your test cases are running in your browser automatically and it gets closed after the test cases are over.
You have automated your development.
Thank you.
Final source code can be found here.
References
For more API methods on Selenium WebDriver, visit,