Reputation: 2077
I'm working on an Angular app which uses ng-repeat to make a table. One of the users found that the table sometimes contains duplicate entries, which I confirmed visually, then promptly wrote a Protractor test for.
While writing the test, I noticed that the scope wasn't behaving in a way that I understood.
Naturally, the for-loop on line 61 has access to linkStorage
(line 38), since it is in a higher scope. It logs that all of the objects have been successfully added to the object via the for-loop in the promise on line 47.
However, when I move the confirmation loop outside of the promise, say, before the expect
block...
...
linkStorage
is an empty object.
Looping over the object finds no nested key-value pairs; it is truely empty.
Why is the linkStorage
object populated inside the then statement, but not before the expectation?
Upvotes: 3
Views: 1487
Reputation: 2077
The first example works is due to asynchronousity. Because the .getAttribute
method is non-blocking, the code continues to run past it while it works. Therefore, the console loop is reached before the object has been populated; it's empty.
If you give the asynchronous code some time to run, maybe one second:
...linkStorage
is populated.
Chain multiple promises together to ensure code runs at the correct time.
it('should not have duplicates within the match grid', function() {
// Already on job A, with match grid shown.
var duplicate = false;
var linkStorage = {};
// Save unique links
var uniqueUserLinks = element.all(by.css('div.row table tbody tr td a'));
// get an array of href attributes
uniqueUserLinks.getAttribute('href')
.then(function(hrefs) {
// add the links to the linkStorage object
for (var i = 0; i < hrefs.length; i++) {
// if the link is already there
if( linkStorage[ hrefs[i] ] ) {
// update its counter
linkStorage[hrefs[i]] += 1
duplicate = true;
// there's already one duplicate, which will fail the test
break;
} else {
// create a link and start a counter
linkStorage[hrefs[i]] = 1;
}
};
}).then(function() {
// confirm links have been added to storage
for(var link in linkStorage) {
console.log('link:', link );
console.log('number:', linkStorage[link] );
}
}).then(function() {
expect(duplicate).toBe(false);
});
});
Upvotes: 3