Marc
Marc

Reputation: 13

Protractor Angular cannot get the count of elements

I'm trying to write a test where I check the ammount of items in a ng-repeat. After that I add 1 item to that ng-repeat and I want to see if the old value+1 is equal to the new value.

This is my html:

<tr ng-repeat="list in listData.myLists">...</tr>

And my test

describe("list test", function(){
    it('Description of the test', function(){
        browser.get('app/#/list');

        var list = element.all(by.repeater('list in listData.myLists'));
        var ammount;

        list.count().then(function(c) {
            ammount = c;
        });

        ... Here I add an item


        var secondAmmount = element.all(by.repeater('list in listData.myLists')).count();

        expect(secondAmmount).toEqual(ammount + 1);
    });
});

But I'm getting 7 is not equal to NaN.

I have also tried just adding the list.count() + 1 directly into the toEquals method but then I get an object instead of a number.

Is there something I'm doing wrong here? Thanks for any help in advance

Upvotes: 1

Views: 2743

Answers (2)

Isaac Lyman
Isaac Lyman

Reputation: 2205

Yep! What's tripping you up is asynchronous programming. The problem with your test is that the second half of the test (after Here I add an item) is evaluated before ammount = c; is evaluated, because your first then() statement is still waiting for count() to come back. So when the expect() statement is hit, ammount still doesn't have a value and adding 1 to it won't work (because it's still null, at least for a few milliseconds). It's funny, but that's how promises work.

The following code will do the trick:

describe("list test", function(){
    it('Description of the test', function(){
        browser.get('app/#/list');

        var list = element.all(by.repeater('list in listData.myLists'));

        list.count().then(function(amount) {

            // ... Here I add an item ...

            var secondAmount = element.all(by.repeater('list in listData.myLists')).count();

            expect(secondAmount).toEqual(amount + 1);
        });
    });
});

It's important to wait for the list.count() promise to come back (asynchronously) before trying to do something with the value it returns. That's what the then() statement is for; it forces the rest of the test to wait for the count() to finish. That way everything happens in the order you expect.

This is necessary because you are using amount + 1. Protractor's expect() statements understand how to use promises, but not if you are modifying the return values. We can put the secondAmount promise directly inside the expect() statement without a then() function, but we cannot put list.count() + 1 inside an expect() statement.

For more details, you can see this answer. Try to gain a strong understanding of Node.JS asynchronous programming and Javascript promises and it will make your Protractor life so much better!

Upvotes: 10

sam schonstal
sam schonstal

Reputation: 429

Protractor element functions run asynchronously and return promises. try this...

describe("list test", function() {
    it('Description of the test', function () {
        browser.get('app/#/list');

        element.all(by.repeater('list in listData.myLists')).count()
        .then(function (amount) {
            // ... Here You add an item
            element.all(by.repeater('list in listData.myLists')).count()
                .then(function (secondAmount) {
                    expect(secondAmount).toEqual(amount + 1);
                })
        })
    });
});

Upvotes: 1

Related Questions