如何让 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
的功能有问题。
- getWebElement() 是不必要的
- 等待期望(page.isItemInMenu('X')).toBeTruthy();好像不对
- 等待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)
});
});
我正在使用量角器在 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
的功能有问题。
- getWebElement() 是不必要的
- 等待期望(page.isItemInMenu('X')).toBeTruthy();好像不对
- 等待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)
});
});