首页 > 解决方案 > 量角器:如何等待 findElements?

问题描述

我有一个搜索字段,当用户点击输入时,它有一个带有一堆复选框的表格。我需要等待结果加载,然后单击表格第一行上的复选框。

这分为 2 个测试用例,第一个执行搜索,第二个单击结果第一行中的复选框以执行其他操作。

 // Test #2      
 it('should perform the Search', () => {
    po.searchAutocomplete.sendKeys('\n');
  });

 // Test #3
  it('3  : should Activate and Inactivate a Program', () => {
    const r = browser.driver.findElements(by.tagName('p-checkbox'));

    browser.driver.wait(EC.presenceOf(r[0]));

    r[0].click();

    browser.sleep(2000).then(() => {
    });

    r[0].click();  
  });

  // Test #4
  it('4  : should navigate to Create New', () => {
    po.createNewButton.click();
  });

所以,这里有同步问题——我的测试#2 成功运行,但是测试#3 立即开始在这里运行。如果搜索结果太慢,那么我会收到复选框不存在的错误,如果它及时返回就可以了。此外,有时第二次 click() 会导致对象未附加到当前页面,因为测试 #4 中的“新建”导航到另一个页面。

看起来 r[0].clicks 的承诺在页面导航到另一个视图后返回 po.createNewButton.click() 导致对象未附加到当前页面错误。

我需要所有这些操作同步。我放入了 browser.wait 但这不起作用,它只是被忽略了。

我怎样才能解决这个问题?

编辑 - 感谢以下建议。这是我所做的更改并使其正常工作:)

在我的应用程序中,我的标头中有一个使用 Observable.interval 的时钟计时器,此外,我还有一个计时器,它正在 ping 服务器以以固定间隔获取一些数据。由于这些始终在运行并且永远不会完成,因此使用 element.all 语法在 Protractor 中导致各种超时,这就是我切换到 browser.driver.findElement 语法的原因,但由于它的异步性质(如海报所示下面 - 谢谢!)使编码变得困难。

我将计时器包装在以下代码中:

this.ngZone.runOutsideAngular(() => {   // Required to prevent interference with Protractor
  this.updateTimer = Observable.interval(UPDATE_INTERVAL).publish();
  this.updateTimer.subscribe(v => {
    this.doSomething();
  });
});

现在,我可以使用 element.all 而不会超时!

标签: angularprotractor

解决方案


发生这种情况是因为您正在使用driver commands来获取元素。驱动程序命令不等待角度异步任务完成。例如,HTTP在您的情况下,请求、数据加载。(默认情况下,Protractor 将等待角度异步任务结束,然后再继续处理队列中的下一个承诺)。

driver仅当您的应用程序中总是有一些异步活动时,使用命令才有意义。比如一个timer

代替

browser.driver.findElements(by.tagName('p-checkbox'));

利用:

element.all(by.tagName('p-checkbox'));

现在,无论何时使用browser.wait(),您都必须等待条件为真,并在等待结束时放置其余代码,例如:

browser.wait(EC.presenceOf(r[0])).then(() => {
   ...// wait is over. Rest of my code here.
})

建议:请使测试its相互fits独立。如果第一次it失败怎么办?那么后续it也会失败吗?

编辑:测试超时的原因

在您的评论中,您说您禁用了计时器?您确定没有其他计时器在运行吗?Protractor 可能会在两种情况下显示此类消息:

  1. 您的应用程序中正在运行一个计时器,量角器等待它完成但超时。
  2. 您已经添加了使用浏览器等待进行检查的presenseOf and element or isElement Clickable, etc等待,但是该元素从未出现在您添加了等待的页面上。

如果有一个计时器正在运行:(没有正确阅读您的评论。如果上面列表中的点数2对您来说是错误的,下面是一个解决方案。)

如果您超时,那么肯定有一些计时器在您的应用程序的后台运行。我们通常出于各种原因在我们的应用程序中使用它,一个常见的原因是在应用程序中某个特定的不活动时间间隔后从应用程序中注销用户。

既然您超时了,那么您有两个选择。

  1. 使用驱动程序命令。

  2. 禁用角度等待,然后使用量角器命令。

    browser.waitForAngularEnabled(false/true).then(() => {.. rest of codes with specific checking of element's existance, their clickability, etc and then perform the actual opration. })

两者都同样繁琐,因为现在您必须等待一切。你不能使用量角器默认等待角度,finish page loads, HTTP requests, etc因为如果你使用它,那么你最终将永远等待直到超时。

我在这种情况下所做的是:

向应用程序添加一种方法,以禁用特定测试用户的运行计时器。我们使用特定的测试用户进行量角器测试用例,当该用户登录时,该用户可以选择禁用计时器。( An extra dom element which when clicked, removes the timer)。因此,就在用户即将点击登录按钮时,我禁用angular wait,(我的应用程序中的计时器仅在登录后启动)然后我在应用程序中进行特定等待,直到我查看是否存在额外的 DOM 元素并且 isClickable,如果为真然后我点击它。单击后,我重新启用角度等待。在此之后,我可以利用量角器自动等待元素出现。希望这可以帮助。


推荐阅读