Introduction

In the previous article, I spoke about the cucumberjs basics. In this article, we will be talking about integrating protractor with cucumber. If you have not visited my previous article, I ask you to click on this link.

Configuring Protractor

If you have not installed the protractor in your machine, I would recommend you to visit this website (https://www.protractortest.org/#/). This contains all the info on setting up the protractor. In this article, I am using the VScode editor; however, you can use any editor.
Go to VScode editor -> Terminal-> New Terminal
Inside the terminal, please execute the below commands. All the steps are mentioned on the protractor website.
  1. npm install -g protractor
  2. webdriver-manager update
  3. webdriver-manager start
After executing the above commands, we need to check whether protractor is working fine or not. To check that, please consider the below example.
Create a ".js" file in the project and add the below code (Ex: protractorTest.js)
  1. describe('angularjs homepage todo list', function() {
  2. it('should add a todo', function() {
  3. browser.get('https://angularjs.org');
  4. element(by.model('todoList.todoText')).sendKeys('write first protractor test');
  5. element(by.css('[value="add"]')).click();
  6. var todoList = element.all(by.repeater('todo in todoList.todos'));
  7. expect(todoList.count()).toEqual(3);
  8. expect(todoList.get(2).getText()).toEqual('write first protractor test');
  9. // You wrote your first test, cross it off the list
  10. todoList.get(2).element(by.css('input')).click();
  11. var completedAmount = element.all(by.css('.done-true'));
  12. expect(completedAmount.count()).toEqual(2);
  13. });
  14. });
In order to execute the above code, you need to specify the conf.js file which contains browser and specs details, as shown below.
In the below example, I have given the "directConnect". We use this command in order to directly execute in the browser without starting the "webdriver -manager". This applies only to Chrome and Firefox. The rest of the browsers "directconnect" will not work
  1. exports.config = {
  2. //seleniumAddress: 'http://localhost:4444/wd/hub',
  3. directConnect: true,
  4. specs: ['protractorTest.js']
  5. };
Now in the Terminal, execute the command mentioned below. Your specs should run successfully.
  1. protractor conf.js
After executing the above code successfully, our protractor is working fine. Now, to integrate it with cucumberjs, you need to execute the below command in the terminal.
  1. npm install protractor-cucumber-framework --save-dev
After installing the above command, you can check in your package.config file. Once this installation is done, you can create your first feature file, as shown below.
  1. Feature: Login
  2. In order to login to the application
  3. As a User
  4. I need to enter the Valid username and Password
  5. Scenario: In order to login to the angular app
  6. Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"
  7. When user login with "angular" and "password"
  8. And User enters the Admin "TestUser"
  9. Then user should login succcessfully
The above is the simple feature file which runs only for one test case. You can execute it using below command. I have given the feature file name as "Login".
  1. .\node_modules\.bin\cucumber-js .\features\Login.feature
It will provide you the step definition in the terminal, as shown below.
  1. 1) Scenario: In order to login to the angular app # features\Login.feature:6
  2. √ Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login" # features\stepDefinition\LoginDefinition.js:4
  3. √ When user login with "angular" and "password" # features\stepDefinition\LoginDefinition.js:10
  4. ? And User enters the Admin "UserNames"
  5. Undefined. Implement with the following snippet:
  6. When('User enters the Admin {string}', function (string) {
  7. // Write code here that turns the phrase above into concrete actions
  8. return 'pending';
  9. });
  10. ? Then user should login succcessfully
  11. Undefined. Implement with the following snippet:
  12. Then('user should login succcessfully', function () {
  13. // Write code here that turns the phrase above into concrete actions
  14. return 'pending';
  15. });
You can copy the step definition and implement the same in your "stepdefinition.js" file.
  1. var {Given, When, Then, Before} = require('cucumber');
  2. const { browser, element } = require('protractor');
  3. Before({timeout: 60 * 1000}, function() {
  4. // Does some slow browser/filesystem/network actions
  5. browser.manage().window().maximize();
  6. });
  7. Given(/^open the application "([^"]*)"$/, function (string) {
  8. return browser.get(string);
  9. });
  10. When('user login with {string} and {string}', function (string, string2) {
  11. // Write code here that turns the phrase above into concrete actions
  12. element(by.model('Auth.user.name')).sendKeys(string);
  13. element(by.model('Auth.user.password')).sendKeys(string2);
  14. return console.log("entered the user name and password");
  15. });
  16. When('User enters the Admin {string}', function (string) {
  17. // Write code here that turns the phrase above into concrete actions
  18. element(by.model('model[options.key]')).sendKeys(string);
  19. return console.log("enetered the logged in user name");
  20. });
  21. Then('user should login succcessfully', function () {
  22. // Write code here that turns the phrase above into concrete actions
  23. return console.log("success");
  24. });
Now once the "Logindefinition.js" file is implemented, you need to integrate it with protractor. For that, you need to do some modifications in the "conf.js" files. Create a "protractor.conf.js" file in the project and add the below code.
You can use "directConnect" to directly open the application. You need to add "framework and frameworkPath", In the specs section you need to add the feature file name, and "cucumberOpts" section you can add the step definition file names related to the ".feature" file. If you do not have any tags keep that as "false" as of now.
If you do not know what is "tags" in cucumber, you can refer here.
  1. exports.config = {
  2. //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  3. directConnect:true,
  4. getPageTimeout: 60000,
  5. allScriptsTimeout: 500000,
  6. framework: 'custom',
  7. // path relative to the current config file
  8. frameworkPath: require.resolve('protractor-cucumber-framework'),
  9. capabilities: {
  10. 'browserName': 'chrome'
  11. },
  12. // Spec patterns are relative to this directory.
  13. specs: [
  14. 'features/*.feature'
  15. ],
  16. cucumberOpts: {
  17. require: 'features/stepDefinition/LoginDefinition.js',
  18. tags: false,
  19. }
  20. };

Multiple Test Data and Multiple Scenarios

In the above example, I have created only one scenario which runs for only one test case. In this example, I will explain how to create multiple scenarios with dynamic test data execution.
  1. Feature: Login
  2. In order to login to the application
  3. As a User
  4. I need to enter the Valid username and Password
  5. Background:
  6. Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"
  7. Scenario Outline: Verify the title of the page
  8. Then the title of page is
  9. Scenario Outline: In order to login to the angular app
  10. When user login with "<username>" and "<password>"
  11. And User enters the Admin "<username1>"
  12. Then user should login succcessfully
  13. Then user should logout succcessfully
  14. Examples:
  15. | username | password | username1 |
  16. | angular | password | user1 |
  17. | angular | password | user2 |
Step definition code
  1. var {Given, When, Then, Before, After} = require('cucumber');
  2. const { browser, element } = require('protractor');
  3. Before({timeout: 60 * 1000}, function() {
  4. // Does some slow browser/filesystem/network actions
  5. browser.manage().window().maximize();
  6. });
  7. Given("open the application {string}", function (string) {
  8. return browser.get(string);
  9. });
  10. Then("the title of the page is", function () {
  11. // Write code here that turns the phrase above into concrete actions
  12. browser.sleep(4000);
  13. var titleofPage = browser.getTitle();
  14. titleofPage.then(function(text){
  15. console.log("page title is : "+ text);
  16. });
  17. });
  18. When("user login with {string} and {string}", function (string, string2) {
  19. // Write code here that turns the phrase above into concrete actions
  20. element(by.model('Auth.user.name')).sendKeys(string);
  21. element(by.model('Auth.user.password')).sendKeys(string2);
  22. return console.log("entered the user name and password");
  23. });
  24. When("User enters the Admin {string}", async function (string) {
  25. // Write code here that turns the phrase above into concrete actions
  26. await element(by.model('model[options.key]')).sendKeys(string);
  27. return console.log("enetered the logged in user name");
  28. });
  29. Then("user should login succcessfully", function () {
  30. // Write code here that turns the phrase above into concrete actions
  31. element(by.buttonText("Login")).click();
  32. return console.log("user logged in successfully");
  33. });
  34. Then("user should logout succcessfully", function () {
  35. // Write code here that turns the phrase above into concrete actions
  36. browser.sleep(4000);
  37. return element(by.linkText("Logout")).click();
  38. });

Executing the Scenarios with Tags

In the above example, we saw how to run multiple scenarios. While testing, there will be some test cases we need to keep for smoke testing, integration testing, functional testing. So cucumber, as provided the tags, which help us to execute the particular test case with the help of tags. Let's see how we can do it, by taking the above example.
So in the below feature file, mark one scenario with the tag "@smoke"
  1. Feature: Login
  2. In order to login to the application
  3. As a User
  4. I need to enter the Valid username and Password
  5. Background:
  6. Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"
  7. Scenario: Verify the title of the page
  8. Then the title of the page is
  9. @smoke
  10. Scenario Outline: In order to login to the angular app
  11. When user login with "<username>" and "<password>"
  12. And User enters the Admin "<username1>"
  13. Then user should login succcessfully
  14. Then user should logout succcessfully
  15. Examples:
  16. | username | password | username1 |
  17. | angular | password | user1 |
  18. | angular | password | user1 |
In the conf.js file, you need to add the tag.
  1. exports.config = {
  2. //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  3. directConnect:true,
  4. getPageTimeout: 60000,
  5. allScriptsTimeout: 500000,
  6. framework: 'custom',
  7. // path relative to the current config file
  8. frameworkPath: require.resolve('protractor-cucumber-framework'),
  9. capabilities: {
  10. 'browserName': 'chrome'
  11. },
  12. // Spec patterns are relative to this directory.
  13. specs: [
  14. 'features/*.feature'
  15. ],
  16. cucumberOpts: {
  17. tags: ['@smoke'],
  18. require: 'features/stepDefinition/LoginDefinition.js',
  19. format:'json:cucumber_report.json'
  20. }
  21. };
So when you execute the tag with '@smoke' gets executed.
You can see in the below console. only 2 scenarios are executed w.rt to test data passed.

Generating HTML Reports

Let's see how to generate reports for the above script. In order to generate the report, we need to first create "cucumber_report.json" file. Please add the line of code in conf.js under "cucumberOpts"
  1. exports.config = {
  2. //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  3. directConnect:true,
  4. getPageTimeout: 60000,
  5. allScriptsTimeout: 500000,
  6. framework: 'custom',
  7. // path relative to the current config file
  8. frameworkPath: require.resolve('protractor-cucumber-framework'),
  9. capabilities: {
  10. 'browserName': 'chrome'
  11. },
  12. // Spec patterns are relative to this directory.
  13. specs: [
  14. 'features/*.feature'
  15. ],
  16. cucumberOpts: {
  17. require: 'features/stepDefinition/LoginDefinition.js',
  18. format:'json:cucumber_report.json',
  19. tags: false,
  20. }
  21. };
After executing the above code with command "protractor <name of conf file>.js". The "cucumber_report.json" file will be generated. The next step is to create "index.js file.
  1. var reporter = require('cucumber-html-reporter');
  2. var options = {
  3. theme: 'bootstrap',
  4. jsonFile: './cucumber_report.json',
  5. output: './cucumber_report.html',
  6. reportSuiteAsScenarios: true,
  7. scenarioTimestamp: true,
  8. launchReport: true,
  9. metadata: {
  10. "App Version":"0.3.2",
  11. "Test Environment": "STAGING",
  12. "Browser": "Chrome 54.0.2840.98",
  13. "Platform": "Windows 10",
  14. "Parallel": "Scenarios",
  15. "Executed": "Remote"
  16. }
  17. };
  18. reporter.generate(options);
Execute the command "node index.js" in the terminal. It will redirect you to the reports.html file which opens up in the browser

Running parallel on Multiple Browsers

When you want to execute tests on multiple browsers at the same time parallelly. Then you need to user the Mutiple Capabilities, shown below:
  1. exports.config = {
  2. //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  3. directConnect:true,
  4. getPageTimeout: 60000,
  5. allScriptsTimeout: 500000,
  6. framework: 'custom',
  7. // path relative to the current config file
  8. frameworkPath: require.resolve('protractor-cucumber-framework'),
  9. multiCapabilities:[{
  10. 'browserName': 'chrome'
  11. },{
  12. 'browserName': 'firefox'
  13. }],
  14. // Spec patterns are relative to this directory.
  15. specs: [
  16. 'features/*.feature'
  17. ],
  18. maxSessions:1, //One browser will open at a time.
  19. cucumberOpts: {
  20. tags: ['@smoke'],
  21. require: 'features/stepDefinition/LoginDefinition.js',
  22. format:'json:cucumber_report.json'
  23. }
  24. };
That's it about cucumber, I have not mentioned the customization of conf.js and customization of cucumber reports in this article. That is because it's already available on the websites I mentioned.
Thank You! Happy Coding :-)