【问题标题】:protractor: how to wait for findElements?量角器:如何等待 findElements?
【发布时间】:2018-05-04 09:27:06
【问题描述】:

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

这分为 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 而不会超时!

【问题讨论】:

  • 不错!我希望我能不止一次地对此表示赞同。您需要在区域外运行计时器。感谢您更新您的问题!
  • @SBKDeveloper:在角度区域外运行计时器非常棒!

标签: angular protractor


【解决方案1】:

这是因为您使用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.
})

建议:请让测试itsfits 相互独立。如果第一个 it 失败了怎么办?那么后面的it也会失败?

编辑:测试超时的原因

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

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

如果有计时器在运行:(没有正确读取您的 cmets。如果上面列表中的点号 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 ,如果为真,那么我点击它。单击后,我重新启用角度等待。在此之后,我可以利用量角器自动等待元素出现。希望这会有所帮助。

【讨论】:

  • 不幸的是,我无法使用 element.all,因为我收到此错误 - 失败:等待异步 Angular 任务在 11 秒后完成时超时 - 在等待带有定位器的元素时 - 定位器:By(css选择器、p-radiobutton[value="ACTIVE"]) 以及所有其他选择器的超时。我的标题中有一个计时器,它使用了我禁用的 Observable.timer,但我仍然收到错误并且无法弄清楚是什么原因造成的。
  • @SBKDeveloper:请查看我更新的答案,看看是否对您有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
相关资源
最近更新 更多