我正在用量角器编写E2E测试。我不得不从浏览器中获取信息并多次执行一步。
我正在测试一个将在
时启动的屏幕id
html id不会改变。提交当前表单后再次查询时值会更改。 for(i = 0 ; i < count ; i++){
console.log("counter is "+i);
element(by('id')).evaluate('value').then(function(v) {
// do some action on UI based on v
element(by('id1')).sendKeys(v+v);
// submit etc.,
// some angular code runs in the frontend.
}
// need to wait since webdriver jumps to the next one without this completing
}
许多博客文章/文档建议您不能在循环中使用它,但不建议任何其他方法来执行此操作。
任何建议表示赞赏。
永远不要在循环内部使用protractor元素语句:简单的原因是webdriverJS(量角器)API是异步的。元素语句返回一个promise,当promise继续执行时,该promise将处于未解析状态。这导致不可预测的结果。因此,建议使用递归函数而不是循环。
来源:http://engineering.wingify.com/posts/angularapp-e2e-testing-with-protractor/
编辑:更新的问题,包含工作流程的详细信息。
答案 0 :(得分:2)
当迭代具有异步调用时,通常不建议使用循环。
原因是当getCursuri()
已经等于i
时,在循环的最后一次迭代之后执行第一次异步调用。
因此,它很难打破循环并跟踪count
的值。
解决问题的方法是使用递归函数:
i
但更好的方法是在一个大小与迭代次数相关的数组上使用var count = 3;
var results = [];
function iterate(i, n) {
if(i < n) {
console.log(`counter is ${i}`);
browser.refresh();
return element(by.id('h-top-questions')).getText().then(function(text) {
results.push(`${i}:${text}`);
return iterate(i + 1, n);
});
}
}
iterate(0, count).then(function(){
console.log("done!", results);
});
进行迭代:
promise.map
你也可以继续使用循环。首先,您必须使用var count = 3;
protractor.promise.map(Array(count).fill(0), function(v, i) {
console.log(`counter is ${i}`);
browser.refresh();
return element(by.id('h-top-questions')).getText().then(function(text) {
return `${i}:${text}`;
});
}).then(function(results){
console.log("done!", results);
});
语句在异步函数(ES6)中获取let
的值。
然后使用i
调用所有同步代码来同步执行:
browser.call
答案 1 :(得分:1)
在量角器中循环工作就像这样
describe('Describe something', function() {
var testParams = [1,2,3,4,5,6,7,8,9,10];
beforeEach( function() {
// ...
});
for (var i = 0; i < testParams.length; i++) {
(function (testSpec) {
it('should do something', function() {
// inside loop
});
})(testParams[i]);
};
});
编辑:我可能会误解你的问题,但在我看来你想在页面上完成所有(动态计数)操作,然后再转到下一个?
it('should clear old inspections', function() {
inspectieModuleInspectieFixture.getRemoveInspectionButton().count().then(function (value) {
if(value == 0){
console.log('--- no inspections to remove ---');
}
for(var i = 0; i < value; i++){
//global.waitForClickable(inspectieModuleInspectieFixture.getRemoveInspectionButtonList(i+1));
inspectieModuleInspectieFixture.getRemoveInspectionButtonList(i+1).click();
console.log('iteration '+i + 'count '+value )
};
});
global.wait(5000);
}); */
这会计算页面上的元素,然后它会为找到的元素执行操作
在上面的例子中,我使用容器来保存我的元素,所以我的代码仍然可读(即inspectieModuleInspectieFixture.getRemoveInspectionButton()持有$(“。elementSelectorExample”)
还有一个'global.waitForClickable'评论,这是对我创建的'时间模块'的影响,它扩展了'wait'的功能,在这种情况下,它会一直等到元素是可变/可点击的。< / p>
很容易反映出这样的事情:
waitForElementNoDisplay: function(element){
return browser.wait(function() {
return element.isDisplayed().then(function(present) {
return !present;
})
});
},
这将使量角器WAIT直到一个元素不再显示。(显示:无)
答案 2 :(得分:0)
如果你需要对每个元素执行一些操作,那么最好不要使用循环。使用.map()或.each()或.filter()代替
仍然不太清楚你该做什么,但这里是我做类似任务的例子,当你需要根据页面中的数据做出多少动作时:
class SomePage {
typeValueForEachElement(elements) {
elements.each((elem, index)=> {
elem.getAttribute('value').then(value=> {
elem.sendKeys(value + value)
elem.submit()
})
})
}
}
new SomePage().typeValueForEachElement($$('your locator here'))
这是可能有帮助的api参考
http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.map http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.reduce http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.each http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.filter