angularjs - Using protractor with loops -


loop index (i) not i'm expecting when use protractor within loop.

symptoms:

failed: index out of bound. trying access element @ index:'x', there 'x' elements

or

index static , equal last value

my code

for (var = 0; < max; ++i) {   getpromise().then(function() {     somearray[i] // 'i' takes value of 'max'   }) } 

for example:

var expected = ['expect1', 'expect2', 'expect3']; var els = element.all(by.css('selector')); (var = 0; < expected.length; ++i) {   els.get(i).gettext().then(function(text) {     expect(text).toequal(expected[i]); // error: `i` 3.    }) } 

or

var els = element.all(by.css('selector')); (var = 0; < 3; ++i) {   els.get(i).gettext().then(function(text) {     if (text === 'should click') {       els.get(i).click(); // fails "failed: index out of bound. trying access element @ index:3, there 3 elements"     }   }) } 

or

var els = element.all(by.css('selector')); els.then(function(rawelements) {   (var = 0; < rawelements.length; ++i) {     rawelements[i].gettext().then(function(text) {       if (text === 'should click') {         rawelements[i].click(); // fails "failed: index out of bound. trying access element @ index:'rawelements.length', there 'rawelements.length' elements"       }     })   } }) 

the reason happening because protractor uses promises.

read https://github.com/angular/protractor/blob/master/docs/control-flow.md

promises (i.e. element(by...), element.all(by...)) execute then functions when underlying value becomes ready. means promises first scheduled , then functions run results become ready.

when run this:

for (var = 0; < 3; ++i) {   console.log('1) is: ', i);   getpromise().then(function() {     console.log('2) is: ', i);     somearray[i] // 'i' takes value of 3   }) } console.log('*  finished looping. is: ', i); 

what happens getpromise().then(function() {...}) returns immediately, before promise ready , without executing function inside then. first loop runs through 3 times, scheduling getpromise() calls. then, promises resolve, corresponding thens run.

the console this:

1) is: 0 // schedules first `getpromise()` 1) is: 1 // schedules second `getpromise()` 1) is: 2 // schedules third `getpromise()` *  finished looping. is: 3 2) is: 3 // first `then` function runs, 3 now. 2) is: 3 // second `then` function runs, 3 now. 2) is: 3 // third `then` function runs, 3 now. 

so, how run protractor in loops? general solution closure. see javascript closure inside loops – simple practical example

for (var = 0; < 3; ++i) {   console.log('1) is: ', i);   var func = (function() {     var j = i;      return function() {       console.log('2) j is: ', j);       somearray[j] // 'j' takes values of 0..2     }   })();   getpromise().then(func); } console.log('*  finished looping. is: ', i); 

but not nice read. fortunately, can use protractor functions filter(fn), get(i), first(), last(), , fact expect patched take promises, deal this.

going examples provided earlier. first example can rewritten as:

var expected = ['expect1', 'expect2', 'expect3']; var els = element.all(by.css('selector')); (var = 0; < expected.length; ++i) {   expect(els.get(i).gettext()).toequal(expected[i]); // note, no longer in `then` function , take correct values. } 

the second , third example can rewritten as:

var els = element.all(by.css('selector')); els.filter(function(elem) {   return elem.gettext().then(function(text) {     return text === 'should click';   }); }).click();  // note here first used 'filter' select appropriate elements, , used fact actions `click` can act on array click matching elements. result can stop using loop altogether.  

in other words, protractor has many ways iterate or access element i don't need use loops , i. if must use loops , i, can use closure solution.


Comments

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -