testability.whenStable()返回,testability.isStable()返回false

Mud*_*Mud 5 protractor angular angular-testing

请注意,这并非特定于量角器。问题出在Angular 2内置的可测试性服务上,而Protractor恰好使用了该服务。量角器Testability.whenStable通过调用进行调用waitForAngular。我已经打了一些失败的代码。

我的测试代码如下所示:

await renderFooView();
await interactWithFooView();
Run Code Online (Sandbox Code Playgroud)

第二行失败:

 Failed: No element found using locator: By(css selector, foo-view)
Run Code Online (Sandbox Code Playgroud)

当量角器继续尝试与之交互的代码时,Angular不会呈现“ foo-view”。

如果我在两者之间添加睡眠,那么它可以工作:

await renderFooView();
await browser.sleep(1000);
await interactWithFooView();
Run Code Online (Sandbox Code Playgroud)

显然我不想那样做。对于我来说,量角器最有价值的是“等待角度”机制,该机制消除了脚本中的“等待X”噪声。我想要的是:

await renderFooView();
await browser.waitForAngular();
await interactWithFooView();
Run Code Online (Sandbox Code Playgroud)

实际上,我永远不必手动执行该中间线。每当我拨打与浏览器互动的电话时,量角器都会自动执行。

做一些挖后,我发现,量角器进行调用,它工作正常,但在角2次出现潜在的可测试性机制打破。

在Angular 2下,量角器的“ waitForAngular”类似于以下内容:

let rootElement = window.getAllAngularRootElements()[0];
let testability = window.getAngularTestability(rootElement);
testability.whenStable(callbackThatResumesScriptExecution);
Run Code Online (Sandbox Code Playgroud)

换句话说,它调用Angular的,testability.whenStable并且仅在Angular报告其稳定后才恢复执行。如果我在回调中添加一些日志记录:

testability.whenStable(() => {
    console.log("isStable:", testability.isStable());
    callback();
});
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)

我已经编写了自己的版本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();
Run Code Online (Sandbox Code Playgroud)

如果我编写了一个手动轮询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
Run Code Online (Sandbox Code Playgroud)

那么...为什么轮询isStable()有效,但是等待whenStable()回调不起作用?更重要whenStable()的是,当下一次调用(无插入代码)显示isStable()错误时,为什么还要报告应用程序稳定?

San*_*uli 0

我过去在使用 Protractor 和 Angular 应用程序时遇到过类似的问题。就我而言,有一个第三方插件的运行时间比预期的要长。因此,isStable 标志将显示 false,直到完全加载为止。我们深入研究并发现有两种方法可以解决这个问题:

1)删除端到端测试套件中的第三方集成并运行测试(这解决了问题,我们不需要使用 browser.sleep

2) 编写一个辅助函数,它将持续 ping 可测试性 api 并监视 isStable 标志。它将等待标志变为真,然后继续测试。这就像在等待角度之上添加等待角度包装器。

我们选择了第一个解决方案,因为这有帮助。

附带说明:您也可能在代码中的某处缺少等待,因为承诺未得到解决,并且测试在搜索元素之前不会等待 isStable 标志。您可以在测试中关闭 Selenium Promise 管理器并尝试查看是否有任何 Promise 被拒绝?您可以通过在量角器配置文件中添加一个标志来做到这一点:SELENIUM_PROMISE_MANAGER: false