Protractor JS e2e testing framework - gpawade/Protractorjs-sample GitHub Wiki
This week I started exploring the Protractor JS. Protractor is an end-to-end test framework for AngularJS applications. But we can use it for non-angular application too.
I've created calculator page for which we write the e2e test in Protractor.
//index.html
<html>
<head>
<title>Hello world</title>
<link rel="stylesheet" href="css/site.css">
<script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<body>
<h1>Welcom...Protractor hello test spec</h1>
<div>
Number 1 : <input type="text" id="number1" />
<br/>
Number 2 : <input type="text" id="number2" />
</div> <br/>
<input id="btnAdd" type="button"
value="Add" onclick="add();" /> <br/>
<span id="result"></span> <br/>
<script type="text/javascript">
function add(){
var num1 = parseInt($("#number1").val());
var num2 = parseInt($("#number2").val());
$("#result").text(num1 + num2);
}
</script>
</body>
</html>
Protractor is wrapper around WebDriverJS to automate e2e testing for Angular JS.
You need node npm package manager to install it.
$ npm install -g protractor
This willl install two commandline tools, protractor
and webdriver-manager
.
The webdriver-manager
is a tool to get the instance of Selenium server running locally.
$ webdriver-manager update
Now, we can start the server with
$ webdriver-manager start
This will start the selenium server at http://localhost:4444/wd/hub.
Protractor need two files to run, a spec file and a configuration file. Before we start writing spec, we follow below directory structure for tests.
Project Folder/
|-- css/
|-- js/
|-- index.html
|-- tests/
|-- unit/
|-- e2e/
|-- po/ //page object
|- indexPage.js
|-- cal-spec.js
|-- config.js
The config file tells the protractor where your spec file are, and what will be the selenium server address. Also we can set the browser details here. Chrome is the default browser.
Here's the sample file -
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
'browserName': 'firefox'
},
// for global setting
onPrepare : function(){
// for non-angular application
browser.ignoreSynchronization = true;
}
specs: ['cal-spec.js']
};
onPrepare : here we can set the global setting before test execution start. Protractor is build for Angular js. If we need to use it for non-angular application, we need set browser.ignoreSynchronization = true;
before spec execution started. So I declared it in onPrepare function.
Copy the following into calc-spec.js
describe("calculator spec", function(){
beforeEach(function(){
browser.get('http://127.0.0.1:8080/index.html');
});
it("should add two number", function(){
element(by.css('#number1')).sendKeys(12);
element(by.css('#number2')).sendKeys(12);
element(by.css('#btnAdd')).click();
var result = element(by.css('#result')).getText();
expect(result).toEqual('24');
});
}
The describe , it and beforeEach syntax is from the Jasmine framework. browser is a global created by Protractor, which is used for browser-level commands such as navigation with browser.get.
Now run the test with:
$ protractor tests/e2e/config.js // this is relative path to config.js file.
$ protractor --elementExplorer --browser firfox
// --browser is optional, chrome is default browser
These are the js files where you map the elements and write the functions to perform actions; we should write the seperate page object for maintanable tests.
Here's the example. How we can rewrite above example.
Your index page object file
//indexPage.js
var IndexPage = function(){
this.txtNum1 = element(by.css('#number1'));
this.txtNum2 = element(by.css('#number2'));
this.result = element(by.css('#result'));
this.addClick = function(){
element(by.css('#btnAdd')).click();
};
this.get = function(){
browser.get('http://127.0.0.1:8080/index.html');
}
}
module.exports = IndexPage;
Your test file
var IndexPage = require('./po/indexPage.js');
describe("calculator spec", function(){
var indexPage = new IndexPage();
beforeEach(function(){
indexPage.get();
});
it("should add two number", function(){
indexPage.txtNum1.sendKeys(12);
indexPage.txtNum1.sendKeys(12);
indexPage.addClick()
var result = indexPage.result.getText();
expect(result).toEqual('24');
});
}