我正在使用量角器和放大器实现角度4应用的自动化。黄瓜框架。
单击简单按钮获取错误。 (并非所有时间)
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我认为没有必要设置等待时间,因为量角器足够聪明以解决承诺
我的项目详情如下:
节点:v6.10.3 量角器: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 (部分内容)
"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"
}
};
提前致谢
更新28-Aug&#39;
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;
}
}
}
答案 0 :(得分:2)
黄瓜的默认超时为5秒。 https://github.com/parse-community/parse-server/wiki#hosting-services(到10秒)为我工作。 Setting default time。此问题可能是因为应用程序已关闭。
@quirimmo感谢您的支持。
答案 1 :(得分:1)
两件事:
1)在配置中通过以下命令使用量角器WebDriver Control Flow
时,请务必禁用async/await
:
SELENIUM_PROMISE_MANAGER: false
这里是官方文档中的属性规范:
启用/禁用WebDriver控制流程。 WebDriverJS(和extention,Protractor)使用控制流来 管理命令执行和承诺的顺序 已解决(有关详细信息,请参阅docs / control-flow.md)。 但是,正如引入
async
/await
之类的语法一样,WebDriverJS也有 决定弃用控制流程,让用户管理 异步活动本身(详情请点击: https://github.com/SeleniumHQ/selenium/issues/2969)。 目前,WebDriver控制流仍默认启用。您 可以通过设置环境变量来禁用它SELENIUM_PROMISE_MANAGER
到0
。在Q4的webdriver版本中 2017年,默认情况下将禁用控制流程,但您将是 能够通过将SELENIUM_PROMISE_MANAGER
设置为重新启用它1
。稍后,将删除控制流程 好。如果您不喜欢管理环境变量,那么 可以在配置文件中设置此选项,Protractor将 处理启用/禁用控制流程。设置这个 选项的优先级高于SELENIUM_PROMISE_MANAGER
环境变量。 @type {boolean =}
2)您确定Node 6.10.3支持async/await
吗?我记得async/await
的官方默认支持是自Node 7.6
答案 2 :(得分:1)
对我来说,(我没有使用async / await),我正在使用
SELENIUM_PROMISE_MANAGER: true,
protractor.conf.js中的
在我的hooks.ts中,我需要其中一个:
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);
});
这是我的导入:
import { Before, After, BeforeAll, defineSupportCode, Status, setDefaultTimeout } from 'cucumber';