如何让 Protractor 的 ElementArrayFinder 'each' 函数在进入下一次迭代之前等待当前操作完成?

How to make Protractor's ElementArrayFinder 'each' function wait for the current action to complete before advancing to next iteration?

我正在使用量角器在 Angular 8 应用程序中进行端到端测试,但我目前无法按需要进行 'each' 循环工作。 在我的页面对象中,我创建了一个 returns 一个 ElementArrayFinder 的方法。

public getCards(): ElementArrayFinder {
return element.all(
  by.css(
    `${this.baseSelector} .board-body cs-medication-card`,
  ),
);

}

对于返回的每个元素,我想执行一组操作,包括单击打开菜单列表的按钮(当菜单打开时,除菜单列表外,所有视图上都有一个覆盖元素) 并选择其中一个选项。在我的测试中,我有这个:

await page.board
  .getCards()
  .each(async (el: ElementFinder) => {
    await until.invisibilityOf(await page.getOverlay());
    await el
      .element(by.css('.card-header .actions'))
      .getWebElement()
      .click();

    await expect(page.isItemInMenu('X')).toBeTruthy();
    await page
      .getMenuItemByLabel('X')
      .getWebElement()
      .click();
  });

我原以为它会为每张卡片单击操作按钮,检查该选项是否在列表中,然后单击该选项。

发生的事情是量角器似乎试图同时做所有事情,因为它说它不能点击操作按钮,因为覆盖在它上面。如果上一次迭代中的操作未完成,则覆盖按钮的唯一方法是。我已经投入了 ExpectedCondition 以等待覆盖层不可见但没有运气。如果 ElementArrayFinder 只返回一个元素,它会执行预期的操作。

我没有想法,任何帮助将不胜感激。

我觉得each的功能有问题。

  1. getWebElement() 是不必要的
  2. 等待期望(page.isItemInMenu('X')).toBeTruthy();好像不对
  3. 等待until.invisibilityOf(等待page.getOverlay());我不确定它是否有效。

请尝试以下代码:

await page.board
  .getCards()
  .each(async (el: ElementFinder) => {
    // await until.invisibilityOf(await page.getOverlay());

    browser.sleep(10*1000) 
    await el
      .element(by.css('.card-header .actions'))
      .click();

    // expect(await page.isItemInMenu('X')).toBeTruthy();

    await page
      .getMenuItemByLabel('X')
      .click();
  })
  .catch((err)->{  // use catch() to capture any runtime error in previous each
    console.log('err: ' + err)
  })

如果以上代码有效,您可以再次还原 expect 和 运行,然后删除 browser.sleep() 并还原您的 await until.invisibilityOf(....) 和 运行再次.

量角器的 each 是异步的。 当您需要对元素数组执行某些操作(例如获取文本或计数)时它很好,但当您需要执行某种场景时它不是最佳选择。 我建议使用任何其他方式,如 for 循环。

另一种解决方法(由于 .each 的异步性质,它可能再次不起作用)是首先等待覆盖出现并等待它消失。

each功能几乎没有用。它甚至不等待 each 函数返回的承诺。

await $$('...').each((ele, index) => {
   return ele.$('.fake_class').click().then(() => {
       console.log(`the item ${index} is clicked.`)
       return browser.wait(5000)
   });
});