Node.js 将ElementArrayFinder.filter()与async/await一起使用

Node.js 将ElementArrayFinder.filter()与async/await一起使用,node.js,selenium-webdriver,protractor,automated-tests,Node.js,Selenium Webdriver,Protractor,Automated Tests,在过去几年中,我一直在使用以下函数过滤启用Webdriver控制流的元素数组: filterElementsByText (elemList, comparator, locator) { return elemList.filter((elem) => { let searchTarget = locator ? elem.element(locator) : elem return searchTarget.getText().then((text) => t

在过去几年中,我一直在使用以下函数过滤启用Webdriver控制流的元素数组:

filterElementsByText (elemList, comparator, locator) {
  return elemList.filter((elem) => {
    let searchTarget = locator ? elem.element(locator) : elem
    return searchTarget.getText().then((text) => text === comparator)
  })
}
我现在正在尝试将我的repo迁移到使用async/await,这需要关闭控制流

这个转换非常成功,但是我在上面的函数中遇到了问题。间歇性地,我看到以下错误:

失败:java.net.ConnectException:连接被拒绝:连接

我能够用我编写的测试用例重现这个问题,尽管在我自己的应用程序中发生的频率要高得多

let todoList = element.all(by.repeater('todo in todoList.todos'))
let todoText = element(by.model('todoList.todoText'))
let todoSubmit = element(by.css('[value="add"]'))

let addItem = async (itemLabel = 'write first protractor test') => {
  await todoText.sendKeys(itemLabel)
  return todoSubmit.click()
}

let filterElementsByText = (elemList, comparator, locator) => {
  return elemList.filter((elem) => {
    let searchTarget = locator ? elem.element(locator) : elem
    return searchTarget.getText().then((text) => {
      console.log(`Element text is: ${text}`)
      return text === comparator
    })
  })
}

describe('filter should', () => {
  beforeAll(async () => {
    browser.ignoreSynchronization = true
    await browser.get('https://angularjs.org')

    for (let i = 0; i < 10; i++) {
      await addItem(`item${i}`)
    }
    return addItem()
  })

  it('work', async () => {
    let filteredElements = await filterElementsByText(todoList, 'write first protractor test')
    return expect(filteredElements.length).toEqual(1)
  })
})
对于简化的测试用例,它似乎发生在5-10%的执行中(不过,有趣的是,它似乎在第一次出现时发生得更频繁)


我的问题是,这感觉像是Webdriver中的一个bug,但我不确定什么情况会导致该错误,所以我不确定如何继续。

对于任何阅读和思考的人来说,我自己的应用程序的问题是双重的

首先,如原始问题的注释所述,ElementArrayFinder.filter()会导致此错误,因为它会对数组中的每个元素运行并行请求

其次(在原始问题中并不明显),我没有像本测试用例中所描述的那样传递ElementArrayFinder,而是实际传递数组中每个元素的链接子元素,例如:

element.all(by.repeater('todo in todoList.todos').$$('span')
在查看Webdriver输出时,我注意到这会导致并行检索所有这些定位器,从而导致相同的错误

我可以通过以下方式解决这两个问题:

let filterElementsByText = async (elemList, comparator, locator) => {
  let filteredElements = []
  let elems = await elemList
  for (let i = 0; i < elems.length; i++) {
    let elem = await elems[i]
    let searchTarget = locator ? elem.element(locator) : elem
    let text = await searchTarget.getText()
    if (text === comparator) {
      filteredElements.push(elem)
    }
  }
  return filteredElements
}
让filterElementsByText=async(elemList、比较器、定位器)=>{
让filteredElements=[]
让elems=等待elemList
for(设i=0;i

这解除了我的阻碍,但这些函数在async/await中无法使用,这仍然是一个问题。

有时,如果我增加测试中创建的项目数(我经常使用250个),我会更频繁地产生问题,但这也只是一个轶事,如果控制流打开时不会发生,这可能是因为在某个地方,代码试图同时解析多个承诺,而应该等待前一个承诺被解析。尝试编写
filterElementsByText
,在循环中使用一些
Wait
,而不使用任何
map
filter
来查看是否存在这种情况。在不使用ElementArrayFinder.filter()的情况下编写自己的筛选函数似乎是可行的,也是一个很好的解决方法,但我正在尝试理解此错误的本质。我可以看出你所描述的多重承诺情况实际上会发生在这里。。但是这如何导致“连接被拒绝”?Selenium命令打开与驱动程序的连接,发送http请求,然后关闭连接。因此,我猜想,同时执行多个命令会使驱动程序的连接尝试溢出,在某种程度上,连接被拒绝时,驱动程序会回复
,但它实际上对我自己的应用没有帮助。所以filter()不是罪魁祸首,但我不知道实际的问题是什么。
let filterElementsByText = async (elemList, comparator, locator) => {
  let filteredElements = []
  let elems = await elemList
  for (let i = 0; i < elems.length; i++) {
    let elem = await elems[i]
    let searchTarget = locator ? elem.element(locator) : elem
    let text = await searchTarget.getText()
    if (text === comparator) {
      filteredElements.push(elem)
    }
  }
  return filteredElements
}