function timed out after 5000 milliseconds - Angular 4 - Protractor & cucumber

我怕爱的太早我们不能终老 提交于 2019-12-24 08:20:42

问题


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,
Css,
Id,
Js,
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;
    }
 }
}

回答1:


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.




回答2:


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




回答3:


For me, (I am not using async/await), I am using

 SELENIUM_PROMISE_MANAGER: true,

in protractor.conf.js

In my hooks.ts, I need either one of these:

    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';


来源:https://stackoverflow.com/questions/45852631/function-timed-out-after-5000-milliseconds-angular-4-protractor-cucumber

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!