Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am automating an angular 4 application with protractor & cucumber framework.

Getting error for a simple button click. (Not all the times)

1) Scenario: Scenario 2 - features\Home.feature:9
   Step: Then Click on edit button - features\Home.feature:11
   Step Definition: stepDefinitions\FirstStep.ts:31
   Message:
     Error: function timed out after 5000 milliseconds
       at Timeout.<anonymous> (C:\MyWorkspace\protractor-cucumber-final\protractor-cucumber-final\node_modules\cucumber\lib\user_code_runner.js:91:22)
       at ontimeout (timers.js:386:14)
       at tryOnTimeout (timers.js:250:5)
       at Timer.listOnTimeout (timers.js:214:5)

Checked here I believe no need to set wait times as protractor is intelligent enough to resolve promises

my project details as follows:

Node: v6.10.3 protractor: v5.1.2

StepDefinition.ts:

let homePage = new HomePage();
Then(/^Click on edit button$/, async () => {
   await homePage.clickEditButton();

HomePage.ts:

async clickEditButton() {
    console.log('clicking on Edit Button');
    await this.editButton.click();

package.json (part of it)

"main": "index.js",
"scripts": {
 "test": "protractor config/config.js",
 "webdriver-start": "webdriver-manager start",
 "webdriver-update": "webdriver-manager update"
"dependencies": {
  "chai": "^4.0.2",
  "cucumber": "^2.3.0",
  "mkdirp": "^0.5.1",
  "protractor": "^5.1.1",
  "protractor-cucumber-framework": "^3.1.0"
"devDependencies": {
  "chai-as-promised": "^6.0.0",
  "cucumber-html-report": "^0.6.0",
  "cucumber-html-reporter": "^0.5.2",
  "cucumberjs-allure-reporter": "^1.0.3",
  "pg": "^6.0.3"

config.js

var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
exports.config = {
  seleniumAddress: "http://localhost:4444/wd/hub",
  baseUrl: "http://localhost:4200/",
  framework: "custom",
  frameworkPath: require.resolve("protractor-cucumber-framework"),
  specs: ["../features/*.feature"],
  exclude: "../features/database.feature",
  resultJsonOutputFile: "./reports/json/protractor_report.json",
  onPrepare: function() {
      // browser.ignoreSynchronization = true;
      browser.manage().window().maximize();
      global.expect = chai.expect;
  cucumberOpts: {
      strict: true,
      format: ["pretty"],
      require: ["../stepDefinitions/*.js", "../support/*.js"],
      tags: "@micro" 

Thanks in advance

UPDATED 28-Aug'17:

ManageRecipeStep.ts

import {defineSupportCode} from 'cucumber';
import {ManageRecipePage} from "../pages/ManageRecipePage";
var chai = require("chai");
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
let expect = chai.expect;
Then(/^Cancel button should be displayed$/, async () => { 
 await expect(manageRecipePage.getCancelButton()).to.eventually.equal('Cancel');

ManageRecipePage.ts

 import {ActionUtil} from "../utils/ActionUtil";
 import {BasePage, IdentificationType} from "../utils/BasePage";
 const Locators = {
    cancelByText: {
      type:IdentificationType[IdentificationType.PartialButtonText],
      value: "Cancel"
 let actionUtil = new ActionUtil();
 export class ManageRecipePage extends BasePage {
   async getCancelButton() {
    await actionUtil.getElementText(Locators.cancelByText);

ActionUtil.ts

 import {BasePage} from "./BasePage";
 export class ActionUtil {
   private basePage: BasePage = new BasePage();
   async getElementText(obj) {
    let attempts = 0;
    while(attempts < 2) {
        try {
            return await this.basePage.ElementLocator(obj).getText();
        } catch(StaleElementException) {
            console.log("EXCEPTION while getting Text" + StaleElementException);
        attempts++;
    return null; // todo: this case

BasePage.ts

import { browser, element, by, protractor, $$, $ } from 'protractor';
export enum IdentificationType {
Xpath,
Name,
PartialLinkText,
ClassName,
PartialButtonText
export class BasePage {
 ElementLocator(obj) {
    switch (obj.type) {
        case IdentificationType[IdentificationType.Xpath]:
            return element(by.xpath(obj.value));
        case IdentificationType[IdentificationType.ClassName]:
            return element(by.className(obj.value));
        case IdentificationType[IdentificationType.Id]:
            return element(by.id(obj.value));
        case IdentificationType[IdentificationType.Js]:
            return element(by.js(obj.value));
        case IdentificationType[IdentificationType.Css]:
            return element(by.css(obj.value));
        case IdentificationType[IdentificationType.PartialButtonText]:
            return element(by.partialButtonText(obj.value));
        default:
            break;

Default timeout for cucumber is 5 sec. Setting default time (to 10 sec) worked for me. Example is here. This issue might be because application is down.

@quirimmo Thanks for your support.

    BeforeAll({ timeout: 60 * 1000 }, () => {
      setDefaultTimeout(60 * 1000);
      return browser.get(config.baseUrl);
    BeforeAll({ timeout: 60 * 1000 }, () => {
      defineSupportCode( ({ setDefaultTimeout }) => {
        setDefaultTimeout(60 * 1000);
      return browser.get(config.baseUrl);

Here is my import:

   import { Before, After, BeforeAll, defineSupportCode, Status, setDefaultTimeout } from 'cucumber';
                Where should the hooks.ts file go? Is it simply a case of requiring the file in the cucumberOpts?
– Michael Martinez
                Jan 18, 2019 at 16:05

Two things:

1) Be sure to disable the WebDriver Control Flow when using protractor with async/await through the following command in the config:

SELENIUM_PROMISE_MANAGER: false

Here the spec of the property from the official doc:

Enable/disable the WebDriver Control Flow. WebDriverJS (and by extention, Protractor) uses a Control Flow to manage the order in which commands are executed and promises are resolved (see docs/control-flow.md for details). However, as syntax like async/await are being introduced, WebDriverJS has decided to deprecate the control flow, and have users manage the asynchronous activity themselves (details here: https://github.com/SeleniumHQ/selenium/issues/2969). At the moment, the WebDriver Control Flow is still enabled by default. You can disable it by setting the environment variable SELENIUM_PROMISE_MANAGER to 0. In a webdriver release in Q4 2017, the Control Flow will be disabled by default, but you will be able to re-enable it by setting SELENIUM_PROMISE_MANAGER to 1. At a later point, the control flow will be removed for good. If you don't like managing environment variables, you can set this option in your config file, and Protractor will handle enabling/disabling the control flow for you. Setting this option is higher priority than the SELENIUM_PROMISE_MANAGER environment variable. @type {boolean=}

2) Are you sure that Node 6.10.3 supports async/await? I remember that the official default support for async/await is since Node 7.6

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.