由于在量角器中使用each()方法,导致出现以下错误。过去它运行良好,但现在始终因该错误而失败。
失败:过时的元素引用:元素未附加到页面文档
element.all(bars).each((element) => element.getCssValue('width'))
是否有其他选择或原因?
(为清楚起见,我要做的就是获取一组称为bar的Web元素中每个元素的宽度。)
谢谢!
答案 0 :(得分:3)
简而言之,这是因为each()
只是针对所有元素同时触发了命令。在您的情况下,您可能需要这样做element.all(bars).getCssValue('width')).then(array => {/*do what you want with returned array here*/})
*已编辑*
你想做的是
element.all(bars).getCssValue('width')).then(array => {
// tests is at least one element will not be "0px"
let elementHasWidth = array.some(elem => elem !== "0px");
expect(elementHasWidth).toBe(true);
})
答案 1 :(得分:3)
由于Protractor和Selenium从Web驱动程序控制流和WebDriverJS Promise Manager演变为原始承诺,因此现有代码中的此类新问题很可能会导致。您曾经能够编写看起来像同步代码的代码,并且在工具箱的内部,工具包会将其转换为异步代码,等待DOM加载并在页面上运行JavaScript。向前need to convert your code前进,以明确使用async/await
或promises。 (请参阅硒更改here背后的原因。)
不幸的是,即使是在Protractor文档中,很多旧的(早于2019年)示例都是以同步方式编写的,因此您在遵循它们时应格外小心。更不幸的是,you cannot mix async
code with Control Flow code,并且如果您尝试执行该操作,则所有控制流都将被禁用,并且依赖它的某些测试可能会开始失败。
对了,bars
的值是多少?量角器by
对象的工作方式不同于本机WebDriver定位器,并且我不确定它们是否可重用。尝试使用by.name('bars')
或其他代替bars
的东西。
由于涉及到所有承诺,您的案子很棘手。 element.getCssValue
返回一个承诺。由于您正在尝试从中获取true
或false
值,因此建议使用简化器。
let nonZero = element.all(by.name('bars')).reduce((acc, elem) => {
return acc || elem.getCssValue('width').then( (width) => width > 0 );
}, false);
在更复杂的情况下,您可以使用all().each()
,但必须注意确保在each
内所做的任何操作都不会影响DOM,因为一旦这样做,它就有可能使其余的DOM失效。数组。
如果您可能要用最终的操作来修改页面,那么,尽管看起来很丑陋,您需要循环查找元素:
for (var i = 0; true; i++) {
let list = element.all(by.css('.items li'));
if (i >= await list.count();)
break;
list.get(i).click();
};
答案 2 :(得分:1)
在您的错误声明之前尝试使用以下代码:
browser.wait(function() {
return element.all(bars).isPresent().then(function(result) {
return result;
});
}, 5000);
答案 3 :(得分:0)
感谢所有提供帮助的人。如果导致错误,请重试该解决方案。由于元素的实时性,元素引用在获得CSS宽度之前就发生了变化。