简体   繁体   English

量角器browser.wait不适用于Angular上的element(by())

[英]Protractor browser.wait doesn't work with element(by()) on Angular

For what reason(s) could this code fail ( no element found )... 出于什么原因,此代码可能失败( 未找到任何元素 )......

   element(by.id('loginButton')).click(); // triggers route change
   browser.wait(element(by.tagName('myComponent')).isPresent(), 10000, 'timeout');
   element(by.tagName('myComponent')).click();

...while this code works ? ...这段代码有效吗?

   element(by.id('loginButton')).click(); // triggers route change
   const eC = protractor.ExpectedConditions;
   browser.wait(eC.visibilityOf(element(by.tagName('myComponent'))), 10000, 'timeout');
   element(by.tagName('myComponent')).click();

I'm working with Angular 5.2.5, Protractor 5.3.0 and Jasmine 2.8.0. 我正在使用Angular 5.2.5,Protractor 5.3.0和Jasmine 2.8.0。

May be related : I could also have asked why I need to add a browser.wait() while element(by()) is supposed to be automatically added in the ControlFlow by Protractor, but there are already lots of related questions ( here , here , there , there ,...), with no clear answer unfortunately. 可能是相关的 :我也可以问为什么我需要添加一个browser.wait()element(by())应该由Protractor自动添加到ControlFlow中,但是已经有很多相关的问题( 这里在这里 ,...),没有明确的答案很遗憾。

The two statements are not equivalent as such. 这两个陈述不等同于此。 I created a simple page like below 我创建了一个简单的页面,如下所示

<html>
    <body>
        <div id="first_name">Tarun</div>
        <script type="text/javascript">
            var div = document.createElement('div');
            div.innerText = 'lalwani';
            div.id = 'last_name';
            setTimeout( () => document.body.appendChild(div),  3000);
        </script>
    </body>
</html>

And a simple test like below 以及如下的简单测试

describe('angularjs homepage todo list', function() {
    it('should add a todo', async function() {
        browser.waitForAngularEnabled(false);

        browser.get('http://0.0.0.0:8000');

        const eC = protractor.ExpectedConditions;

        browser.wait(element(by.id('last_name')).isPresent(), 10000, 'timeout');
    });
});

When you run you will find the output is 当你运行时,你会发现输出是

Started
...
1 spec, 0 failures
Finished in 0.617 seconds

Now if you change the code to 现在,如果您将代码更改为

describe('angularjs homepage todo list', function() {
    it('should add a todo', async function() {
        browser.waitForAngularEnabled(false);

        browser.get('http://0.0.0.0:8000');

        const eC = protractor.ExpectedConditions;

        browser.wait(eC.visibilityOf(element(by.id('last_name'))), 10000, 'timeout');

    });
});

The output of the same is below 它的输出如下

Started
...
1 spec, 0 failures
Finished in 3.398 seconds

As you can see the visibilityOf actually waited for the object to appear while the previous one didn't. 正如您所看到的, visibilityOf实际上等待对象出现而前一个对象没有出现。

This is because the controlFlow will make isPresent get executed and return the promise returning value of true/false to the wait. 这是因为controlFlow将使isPresent得到执行,并将返回值true或false的promise返回给wait。 While visibilityOf will return a function that the wait can check by calling again and again. 虽然visibilityOf将返回一个wait可以通过反复调用来检查的函数。

You can verify this by adding below in the test 您可以通过在测试中添加以下内容来验证这一点

console.log(typeof eC.visibilityOf(element(by.id('last_name'))))
console.log(typeof element(by.id('last_name')))

The output of same is 它的输出是

function
object

So the assumption your below two statements are same is wrong and that is why you don't get the correct results with the first one 因此,下面两个语句相同的假设是错误的,这就是为什么你没有得到第一个正确的结果

browser.wait(element(by.tagName('myComponent')).isPresent(), 10000, 'timeout');
browser.wait(eC.visibilityOf(element(by.tagName('myComponent'))), 10000, 'timeout');

There is a not-so obvious difference between the two . 两者之间存在着不那么明显的区别。 But the webdriver docs are clear about this. 但是webdriver 文档对此很清楚。

eC.visibilityOf(...) - Returns a function . eC.visibilityOf(...) - 返回一个函数 browser.wait() repeatedly evaluates functions until they return true. browser.wait()重复计算函数,直到它们返回true。

isPresent() - Returns a promise . isPresent() - 返回一个promise browser.wait() does not / cannot repeatedly evalute promises(!) browser.wait() will continue immediately when the promise resolves , regardless of whether it returns true or false. browser.wait()没有/不能重复评估promises(!),当promise解析时,browser.wait()将立即继续,无论它是返回true还是false。

If you want to use isPresent() you can wrap it in a function . 如果要使用isPresent(),可以将其包装在函数中 This allows webdriver to call it over and over. 这允许webdriver一遍又一遍地调用它。

 browser.wait(() => element(by.tagName('myComponent')).isPresent(), 10000, 'timeout');

Works exactly as you expect. 完全按照您的预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM