【问题标题】:Protractor, iterating elements: Failed: stale element reference量角器,迭代元素:失败:过时的元素引用
【发布时间】:2018-10-18 10:04:39
【问题描述】:

我有一组 webdriver 元素,我正在尝试遍历它们以将它们全部删除,除了索引为 0 的元素。此迭代中的进程是异步的。

我尝试了几件事,但似乎都没有。

我目前的方法是使用for of 循环,但我得到的是Failed: stale element reference: element is not attached to the page document

const els = await this.el.getElements(this.s.tm.button.remove)

for (let el of els) {
      if (els.indexOf(el) >= 1) {
        await this.h.waitForSpinner(2147483647)
        await el.click()
        await EC.isVisible(this.s.tm.deleteModal.container)
        await this.h.waitForSpinner(2147483647)
        await this.el.clickElement(this.s.tm.deleteModal.confirmButton)
      }
    }

我也试过用:

element.all(by.css('[data-qa="this.s.tm.button.remove"]')).filter((el, i) => {
      return i >= 1;
    }).each(async (el, i) => {
      await el.click()
      await EC.isVisible(this.s.tm.deleteModal.container)
      await this.h.waitForSpinner(50000)
      await this.el.clickElement(this.s.tm.deleteModal.confirmButton)
    });

但是第二种方法不是等待异步代码。

任何帮助将不胜感激!

====================更新解决方案===================

@yong 迭代 WebDriver 元素集合的解决方案是正确的。

但是,在我的例子中,for loop 中的代码每次删除一个元素,所以有时.get(i) 会尝试获取循环提供的索引页面中不再存在。得到错误:

Failed: Index out of bound. Trying to access element at index: 6, but there are only 5 elements that match locator By(css selector, [data-qa=team-members__button-remove]).

解决方案是使用递减的for loop。这意味着,els_count 的向后循环将始终匹配get(i)。请注意,如果els_count === 10,最后一个索引将是9。所以我们需要做els_count - 1

async deleteAllTeamMembers() {
  await EC.isVisible(await this.el.getFirstElement(this.s.tm.button.invite));
  const els_count = await this.el.getElements(this.s.tm.button.remove).count();

for (let i = els_count - 1; i >= 1; i--) {
  await EC.isVisible(this.el.getElements(this.s.tm.button.remove).get(i))
  await this.el.getElements(this.s.tm.button.remove).get(i).click()
  await EC.isVisible(this.s.tm.deleteModal.confirmButton, 50000)
  await this.el.clickElement(this.s.tm.deleteModal.confirmButton)
  await this.h.waitForSpinner(50000)
}

}

【问题讨论】:

  • 你的问题的关键是每次点击元素,它都会触发页面发生变化,这将使selenium将页面视为新页面,而不是与以前的页面相同的页面循环,因此在前一个循环或第一个循环之前找到的所有元素都不能在新页面中使用。例如:els有两个元素,点击els[0]后,新页面到达,els[1]是在初始页面而不是新页面,所以你不能继续使用els[1] at新页面,如果你想在新页面上使用它,你必须重新找到它。如果你使用它,Stale Reference Error 就会抛出

标签: javascript selenium asynchronous webdriver protractor


【解决方案1】:

尝试这样做。持有对象中的元素,您需要异步访问每个元素并执行如下所示的操作。不需要指定等待

this.searchResults = element.all(by.xpath('<xpath>') // this will hold array of elements

function foo(){
this.searchResults.then(function(runTimeResults){
            for(i=0; i< runTimeResults.length; i++){
                if(i>0){ //click/delete the element if the index > 0
                (function(currentElement){
                    currentElement.click();                 
                    });
                })(runTimeResults[i]);// Need to hold the current ith element in a variable => currentElement
                }
            };
        });
}

【讨论】:

    【解决方案2】:
    const els_cnt = await element.all(by.css('[data-qa="this.s.tm.button.remove"]')).count();
    
    for (let index=1;index<els_cnt;index++) {
        await element.all(by.css('[data-qa="this.s.tm.button.remove"]')).get(index).click();
        await EC.isVisible(this.s.tm.deleteModal.container)
        await this.h.waitForSpinner(50000)
        await this.el.clickElement(this.s.tm.deleteModal.confirmButton)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多