在条件评估为真时获取元素(扩展 ElementArrayFinder)
Take elements while a condition evaluates to true (extending ElementArrayFinder)
我们有一个表示为 ul->li
列表(简化)的菜单:
<ul class="dropdown-menu" role="menu">
<li ng-repeat="filterItem in filterCtrl.filterPanelCfg track by filterItem.name"
ng-class="{'divider': filterItem.isDivider}" class="ng-scope">
<a href="" class="ng-binding"> Menu Item 1</a>
</li>
...
<li ng-repeat="filterItem in filterCtrl.filterPanelCfg track by filterItem.name"
ng-class="{'divider': filterItem.isDivider}" class="ng-scope">
<a href="" class="ng-binding"> Menu Item 2</a>
</li>
</ul>
在位置 N 的某处,有一个分隔符,可以通过 评估 filterItem.isDivider
或检查 a
link(如果是分隔线,它是空的)。
现在,目标是获取位于分隔符之前的所有菜单项。你会如何解决这个问题?
我目前的方法相当通用 - 扩展 ElementArrayFinder
并添加 takewhile()
函数(受 Python 的 itertools.takewhile()
). Here is how I've implemented it (based on filter()
启发):
protractor.ElementArrayFinder.prototype.takewhile = function(whileFn) {
var self = this;
var getWebElements = function() {
return self.getWebElements().then(function(parentWebElements) {
var list = [];
parentWebElements.forEach(function(parentWebElement, index) {
var elementFinder =
protractor.ElementFinder.fromWebElement_(self.ptor_, parentWebElement, self.locator_);
list.push(whileFn(elementFinder, index));
});
return protractor.promise.all(list).then(function(resolvedList) {
var filteredElementList = [];
for (var index = 0; index < resolvedList.length; index++) {
if (!resolvedList[index]) {
break;
}
filteredElementList.push(parentWebElements[index])
}
return filteredElementList;
});
});
};
return new protractor.ElementArrayFinder(this.ptor_, getWebElements, this.locator_);
};
而且,我是这样使用它的:
this.getInclusionFilters = function () {
return element.all(by.css("ul.dropdown-menu li")).takewhile(function (inclusionFilter) {
return inclusionFilter.evaluate("!filterItem.isDivider");
});
};
但是,测试只是挂起,直到 takewhile()
调用达到 jasmine.DEFAULT_TIMEOUT_INTERVAL
。
如果我将 console.log
s 放入循环和之后,我可以看到它正确地将元素推到分隔符之前并在到达分隔符时停止。我可能在这里遗漏了一些东西。
使用量角器 2.2.0.
另外,如果我把问题复杂化了,请告诉我。
也许我遗漏了什么,但是你不能在 ul li a
元素从 getText() 给你一些东西时,将它们存储到某个数组,或者直接在那个循环?
var i = 0;
var el = element.all(by.css('ul li a'));
var tableItems = [];
(function loop() {
el.get(i).getText().then(function(text){
if(text){
tableItems.push(el.get(i));
i+=1;
loop();
}
});
}());
takewhile()
实际上在我从 onPrepare()
中删除 protractor.promise = require("q");
后对我有用 - 这是用来将 protractor.promise
替换为 q
的能够使用像 这样的语法糖。显然,使用 q
代替 protractor.promise
是不安全的。
我现在要做的就是将它添加到 onPrepare()
:
protractor.ElementArrayFinder.prototype.takewhile = function(whileFn) {
var self = this;
var getWebElements = function() {
return self.getWebElements().then(function(parentWebElements) {
var list = [];
parentWebElements.forEach(function(parentWebElement, index) {
var elementFinder =
protractor.ElementFinder.fromWebElement_(self.ptor_, parentWebElement, self.locator_);
list.push(whileFn(elementFinder, index));
});
return protractor.promise.all(list).then(function(resolvedList) {
var filteredElementList = [];
for (var index = 0; index < resolvedList.length; index++) {
if (!resolvedList[index]) {
break;
}
filteredElementList.push(parentWebElements[index])
}
return filteredElementList;
});
});
};
return new protractor.ElementArrayFinder(this.ptor_, getWebElements, this.locator_);
};
用法与filter()
非常相似:
element.all(by.css("ul li a")).takewhile(function (elm) {
return elm.getText().then(function (text) {
return text;
});
});
我们有一个表示为 ul->li
列表(简化)的菜单:
<ul class="dropdown-menu" role="menu">
<li ng-repeat="filterItem in filterCtrl.filterPanelCfg track by filterItem.name"
ng-class="{'divider': filterItem.isDivider}" class="ng-scope">
<a href="" class="ng-binding"> Menu Item 1</a>
</li>
...
<li ng-repeat="filterItem in filterCtrl.filterPanelCfg track by filterItem.name"
ng-class="{'divider': filterItem.isDivider}" class="ng-scope">
<a href="" class="ng-binding"> Menu Item 2</a>
</li>
</ul>
在位置 N 的某处,有一个分隔符,可以通过 评估 filterItem.isDivider
或检查 a
link(如果是分隔线,它是空的)。
现在,目标是获取位于分隔符之前的所有菜单项。你会如何解决这个问题?
我目前的方法相当通用 - 扩展 ElementArrayFinder
并添加 takewhile()
函数(受 Python 的 itertools.takewhile()
). Here is how I've implemented it (based on filter()
启发):
protractor.ElementArrayFinder.prototype.takewhile = function(whileFn) {
var self = this;
var getWebElements = function() {
return self.getWebElements().then(function(parentWebElements) {
var list = [];
parentWebElements.forEach(function(parentWebElement, index) {
var elementFinder =
protractor.ElementFinder.fromWebElement_(self.ptor_, parentWebElement, self.locator_);
list.push(whileFn(elementFinder, index));
});
return protractor.promise.all(list).then(function(resolvedList) {
var filteredElementList = [];
for (var index = 0; index < resolvedList.length; index++) {
if (!resolvedList[index]) {
break;
}
filteredElementList.push(parentWebElements[index])
}
return filteredElementList;
});
});
};
return new protractor.ElementArrayFinder(this.ptor_, getWebElements, this.locator_);
};
而且,我是这样使用它的:
this.getInclusionFilters = function () {
return element.all(by.css("ul.dropdown-menu li")).takewhile(function (inclusionFilter) {
return inclusionFilter.evaluate("!filterItem.isDivider");
});
};
但是,测试只是挂起,直到 takewhile()
调用达到 jasmine.DEFAULT_TIMEOUT_INTERVAL
。
如果我将 console.log
s 放入循环和之后,我可以看到它正确地将元素推到分隔符之前并在到达分隔符时停止。我可能在这里遗漏了一些东西。
使用量角器 2.2.0.
另外,如果我把问题复杂化了,请告诉我。
也许我遗漏了什么,但是你不能在 ul li a
元素从 getText() 给你一些东西时,将它们存储到某个数组,或者直接在那个循环?
var i = 0;
var el = element.all(by.css('ul li a'));
var tableItems = [];
(function loop() {
el.get(i).getText().then(function(text){
if(text){
tableItems.push(el.get(i));
i+=1;
loop();
}
});
}());
takewhile()
实际上在我从 onPrepare()
中删除 protractor.promise = require("q");
后对我有用 - 这是用来将 protractor.promise
替换为 q
的能够使用像 q
代替 protractor.promise
是不安全的。
我现在要做的就是将它添加到 onPrepare()
:
protractor.ElementArrayFinder.prototype.takewhile = function(whileFn) {
var self = this;
var getWebElements = function() {
return self.getWebElements().then(function(parentWebElements) {
var list = [];
parentWebElements.forEach(function(parentWebElement, index) {
var elementFinder =
protractor.ElementFinder.fromWebElement_(self.ptor_, parentWebElement, self.locator_);
list.push(whileFn(elementFinder, index));
});
return protractor.promise.all(list).then(function(resolvedList) {
var filteredElementList = [];
for (var index = 0; index < resolvedList.length; index++) {
if (!resolvedList[index]) {
break;
}
filteredElementList.push(parentWebElements[index])
}
return filteredElementList;
});
});
};
return new protractor.ElementArrayFinder(this.ptor_, getWebElements, this.locator_);
};
用法与filter()
非常相似:
element.all(by.css("ul li a")).takewhile(function (elm) {
return elm.getText().then(function (text) {
return text;
});
});