Protractor: 'wait' doesn't work with “

2020-03-13 05:10发布

问题:

I write Protractor automation tests and faced an issue. Wait command doesn't actually wait for one of the array elements. See the example below: I try to wait for the first element after navigating to webpage.

var category = element.all(by.repeater('category in listCtrl.categories'));
var category2 = $$('.category-name.custom-tooltip-link.ng-binding');
var EC = protractor.ExpectedConditions;

describe('wait for the first category', function() {

    it('wait', function() {
        browser.get('http://www.deep.mg/');

        browser.wait(EC.visibilityOf(category.get(0)), 20000);

        browser.wait(EC.visibilityOf(category2.get(0)), 20000);
    });
});

But test fails with the following error: Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator by.repeater("category in listCtrl.categories").

Error doesn't depend on locator type, because appears for both: "by.repeater" and "by.css". The selectors are ok, test passes after adding 'sleep' command:

var category = element.all(by.repeater('category in listCtrl.categories'));
var category2 = $$('.category-name.custom-tooltip-link.ng-binding');
var EC = protractor.ExpectedConditions;

describe('wait for the first category', function() {

    it('wait', function() {
        browser.get('http://www.deep.mg/');

        browser.sleep(15000);

        browser.wait(EC.visibilityOf(category.get(0)), 20000);

        browser.wait(EC.visibilityOf(category2.get(0)), 20000);

        category.count().then(function(count1) {
            console.log(count1);  //count returns 5, which means there are actually elements in array
        });

        category2.count().then(function(count2) {
            console.log(count2);
        });
    });
});

Also timeout parameter doesn't help, it just ignores it and fails immediately.

So the question is how to wait for a certain element of an array? Am I missing something? Thanks.

回答1:

Make a custom Expected Condition to wait for count of elements in an array to be more than 0:

function presenceOfAll(elementArrayFinder) {
    return function () {
        return elementArrayFinder.count(function (count) {
            return count > 0;
        });
    };
}

Usage:

browser.wait(presenceOfAll(category), 10000);
browser.wait(presenceOfAll(category2), 10000);

Works for me.



回答2:

element.all(by.repeater('category in listCtrl.categories')).get(0) will ALWAYS throw an error if there are no elements to 'get' (source: element.js ElementArrayFinder.prototype.get)

You can do:

browser.wait(function() {
    return category.count().then(function(catCount) {
        if (catCount > 0) {
            return EC.visibilityOf(category.get(0));
        }
    }
}, 20000);

Or you could probably just wait until all the elements are visible, and it would do what you are asking it to do (because it will wait for the 'all' promise to resolve completely anyway, not just break out when it gets the first one):

browser.wait(EC.visibilityOf(category), 20000);