admin管理员组

文章数量:1328366

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.

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.

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.

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.

Share Improve this question edited Mar 21, 2018 at 7:21 Tarun Lalwani 147k11 gold badges213 silver badges276 bronze badges asked Mar 14, 2018 at 11:09 ThCollignonThCollignon 1,2143 gold badges17 silver badges40 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6 +50

There is a not-so obvious difference between the two . But the webdriver docs are clear about this.

eC.visibilityOf(...) - Returns a function. browser.wait() repeatedly evaluates functions until they return true.

isPresent() - Returns a 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.

If you want to use isPresent() you can wrap it in a function. This allows webdriver to call it over and over.

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

Works exactly as you expect.

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.

This is because the controlFlow will make isPresent get executed and return the promise returning value of true/false to the wait. While visibilityOf will return a function that the wait can check by calling again and again.

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');

本文标签: javascriptProtractor browserwait doesn39t work with element(by()) on AngularStack Overflow