Install dependencies:
- cucumber : npm install cucumber (If protractor was installed locally else use npm install -g cucumber). Both protractor and cucumber should be in same scope.
- cucumber-html-reporter: npm install cucumber-html-reporter — save-dev
- chai: npm install chai
- protractor-cucumber-framework: npm install — save-dev protractor-cucumber-framework
My package.json:
you can directly use the package.json and install all dependencies by placing the file under your test project and just running
npm install
package.json:
{
"name": "Test",
"version": "1.0.0",
"description": "Test framework for project Test",
"main": "conf.js",
"keywords": [
"test"
],
"author": "Praveen David Mathew",
"license": "ISC",
"dependencies": {
"chai": "^4.2.0",
},
"devDependencies": {
"cucumber": "^6.0.5",
"cucumber-html-reporter": "^5.1.0",
"protractor-cucumber-framework": "^6.2.0"
}
}
Now create chai expect global keyword:
Protractor uses jasmine out of the box, so when you are using the custom framework the jasmine expect class won’t work.
You have to use another assertion class , we are using chai.
We can use chai expect class by importing it in each step definition
'use strict';
expect = require('chai').expect;
This would be hectic, so work around is to declare expect as global in a separate file.
My chaiAssertions.js:
'use strict';
// Configure chai
global.expect = require('chai').expect;
Create Hook.js:
Hooks are just another stepdefinition file you can name it anything you want. A hook is identified using the keyword After and Before
Here i created a Hook.js file to get screenshot if scenario fails:
hook.js:
var { After, Before } = require('cucumber');
// Asynchronous Promise
After(async function(scenario) {
if (scenario.result.status === 'failed') {
const screenShot = await browser.takeScreenshot();
this.attach(screenShot, "image/png");
}
});
So after each scenario , the code inside after get executed. Which will take screenshot of scenario.result.status is failed.
Now my conf.js
'use strict';
exports.config = {
directConnect: true,
//Running chrome
Capabilities: { browserName: 'chrome'
},
//point spec to feature file , my feature file was under feature folder
specs: ['feature/*.feature'],
//set framework options
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
//just maximizing window before testing
onPrepare: function(){
browser.waitForAngularEnabled(true);
browser.driver.manage().window().maximize();
} ,
//Create html report
onComplete: () => {
var reporter = require('cucumber-html-reporter');
var options = {
theme: 'bootstrap',
jsonFile: './results.json',
output: './results.html',
reportSuiteAsScenarios: true,
launchReport: true,
metadata: {
"App Version":"0.3.2",
"Test Environment": "STAGING",
"Browser": "Chrome 54.0.2840.98",
"Platform": "Windows 10",
"Parallel": "Scenarios",
"Executed": "Remote"
},
output: './report/cucumber_report.html',
};
reporter.generate(options);
},
//set cucumber options
cucumberOpts: {
require: ['./testsuites/*.js','./commons/chaiAssertions.js','./commons/hooks.js'],
strict: true,
format: [], //don't put 'Pretty' as it is depreciated
'dry-run': false,
compiler: [],
format: 'json:results.json', //make sure you are not using multi-capabilities
},SELENIUM_PROMISE_MANAGER: false,
};
Here, i point to the feature file using the property specs: [‘feature/*.feature’],
and glues it to the step definition using cucumberopts> require:
There is no one to one mapping between feature and step definition, the framework automatically finds the step definition that contains the definition for the step from provided step definitions(.js files) in the require field.
Now write feature file:
test.feature
Feature: Google search
Scenario Outline: Log in with given API
Given I navigates to google
And searches for '
'
Then I should see ''
Examples:
|input|this|
|test|pass|
|test2|fail|
Now write step definition:
step.js:
var { Given } = require('cucumber');
Given('I navigates to google', async function () {
await browser.get('https://www.google.com/');
});
Given('searches for {string}', async function (searchValue) {
await element(by.css('input[role="combobox"]')).sendKeys(searchValue)
});
Given('I should see {string}', async function (expectedValue) {
expect(expectedValue).to.equal('pass')
});
so here we are using just Given as during runtime Given ,when then etc will be ignored and only the string after that will be considered
So, even if our feature file has And searches for ‘input’ , we can write step definition as Given(‘searches for {string}’.
Note that we are not using regular expressions to get parameters but the data type.
you might have seen in other tutorials , Given( /^searches for (\w+)$/ ). Its simpler to use the format i have used Given(‘searches for {string}’. Both the approaches works works fine.
Now run the scripts:
protractor conf.js
Report:
Report will be generated under report folder
Framework zip:
Just download and run npm install
To execute , run the command protractor conf.js