注意,这并不是特定于量角器。问题是角2的内置可测性服务,而量角器恰好使用。量角器通过调用Testability.whenStable调用waitForAngular。我撞到了一些代码这是失败的。
我的测试代码如下所示:
await renderFooView();
await interactWithFooView();第二行失败:
Failed: No element found using locator: By(css selector, foo-view)当Protractor继续使用试图与其交互的代码时,角不是完成呈现'foo-view‘的。
如果我在中间加了一个睡眠,它就会起作用:
await renderFooView();
await browser.sleep(1000);
await interactWithFooView();显然我不想那样做。对于我来说,“量角器”的大部分价值是“等待角度”机制,它消除了脚本中的“等待X”噪音。我想要的是:
await renderFooView();
await browser.waitForAngular();
await interactWithFooView();事实上,我不应该手动执行这个中间行。每次我打电话与浏览器交互时,量角器都会自动完成。
在进行了一些深入研究之后,我发现Protractor正在进行调用,它工作正常,但是角2中的底层可测性机制出现了故障。
在角2下,量角器的"waitForAngular“执行如下操作:
let rootElement = window.getAllAngularRootElements()[0];
let testability = window.getAngularTestability(rootElement);
testability.whenStable(callbackThatResumesScriptExecution);换句话说,它调用角的testability.whenStable,只有当角报告它是稳定的时才恢复执行。如果我在回调中添加了一些日志记录:
testability.whenStable(() => {
console.log("isStable:", testability.isStable());
callback();
});isStable()在whenStable回调中始终是正确的,因此角绝对是在正确的时间调用的。
但是,如果在此回调返回之后,我再次轮询isStable(),则它的计算结果为false。
let pollAngularIsStable = `{
let rootElement = window.getAllAngularRootElements()[0];
let testability = window.getAngularTestability(rootElement);
return testability.isStable();
}`;
await renderFooView();
await browser.waitForAngular();
console.log(await browser.executeScript(pollAngularIsStable)); // => false
await interactWithFooView();我编写了我自己版本的browser.waitForAngular,我看到了完全相同的结果:
let waitForAngularStable = `
let callback = arguments[arguments.length - 1];
let rootElement = window.getAllAngularRootElements()[0];
let testability = window.getAngularTestability(rootElement);
testability.whenStable(callback);
`;
await renderFooView();
await browser.executeAsyncScript(waitForAngularStable);
console.log(await browser.executeScript(pollAngularIsStable)); // => false
await interactWithFooView();如果我编写了一个手动轮询isStable()直到返回true的例程,则修复我的脚本:
async function waitForAngular() {
let ms;
for (ms=0; ms<10000; ++ms) {
await browser.sleep(1);
if (await browser.executeScript(pollAngularIsStable)) {
break;
}
}
console.log(`Waited ${ms}ms for Angular to be stable.`);
}
await renderFooView();
await waitForAngular(); // usually waits < 50ms
console.log(await browser.executeScript(pollAngularIsStable)); // => true
await interactWithFooView(); // always works now所以..。为什么轮询isStable()工作,但等待whenStable()回调不起作用?更重要的是,为什么whenStable()报告应用程序是稳定的,而下一个调用(没有中间代码)显示isStable()是假的?
发布于 2019-12-23 10:58:52
过去,当我使用量角器和角度应用时,我也曾遇到过类似的问题。在我的例子中,有一个第三方插件运行的时间比预期的要长。因此,isStable标志将显示false,直到它完全加载为止。我们挖得很深,认为有两种方法可以解决这个问题:
1)删除端到端测试套件中的第三方集成并运行测试(这解决了问题,我们不需要使用browser.sleep )。
2)编写一个助手函数,该函数将持续地ping可测试性api并监视isStable标志。它将等待标志变为真,然后继续进行测试。这就像在等待角包装的基础上添加一个等待角包装器。
我们选择了第一个解决方案,因为这很有帮助。
顺便提一句:您还可能在代码中的某个地方遗漏了等待,因为在搜索元素之前,承诺没有得到解决,而且测试也没有等待isStable标志。您能否在测试中关闭selenium允诺管理器,并尝试查看是否有任何承诺被拒绝?您可以通过在量角器配置文件中添加一个标志: SELENIUM_PROMISE_MANAGER: false来做到这一点。
https://stackoverflow.com/questions/54509647
复制相似问题