1

This question is very close to the question asked in Using protractor with loops but still have not resolved by me in case of tiny difference.

// This script should print button names and its current numbers
var buttons = element.all(by.css('button'));
buttons.count().then(function(cnt){
  for(var i=0;i<cnt;i++) {
    var func = function(i2){ var k=i2; return function(){console.log("#"+k+", name: "+button_name);}}(i);
    buttons.get(i).getText().then(func);
  }
});

The compiler said "ReferenceError: button_name is not defined" that is right. How can I pass the button name inside then() function?

Community
  • 1
  • 1
Volodymyr Nabok
  • 415
  • 1
  • 4
  • 11

2 Answers2

4

You are getting the function name as the argument to your then callback - but currently your func doesn't have a parameter. If you give it one, it'll work:

for (var i=0; i<cnt; i++) {
    var func = function(k) { 
        return function(button_name) {
//                      ^^^^^^^^^^^
            console.log("#"+k+", name: "+button_name);
        };
    }(i);
    buttons.get(i).getText().then(func);
}

or maybe without returning from the IEFE, ther more common pattern might be:

for (var i=0; i<cnt; i++) (function(k) {
    buttons.get(k).getText().then(function(button_name) {
//                                         ^^^^^^^^^^^
        console.log("#"+k+", name: "+button_name);
    });
}(i));

Disclaimer: I'm not saying that this is the best way to use protactor, it's just how promises and closures work. I'd expect protractor to actually provide an iteration method - @finspin seems to have used it.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • That's work fine, thank you! I'm afraid to be boring but why ".then(func);" expression calls without argument that symbolize button text? Like ".then(func(b_text));" – Volodymyr Nabok Sep 03 '15 at 17:06
  • It's the promise that calls your function and supplies the function - if you'd call it instead of passing it wouldn't work. Also, *you* don't have a `b_text` to pass… – Bergi Sep 03 '15 at 18:21
2

I'm not sure if I understand your intention correctly but if you want to print button name attribute and its index, this should do it:

$$('.button').forEach(function (button, index) {
    button.getAttribute('name').then(function (btnName) {
        console.log('#' + index + ', name: ' + btnName);
    });
});
finspin
  • 4,021
  • 6
  • 38
  • 66
  • Actually, my example is a little artificial. What I really want to understand how to use values from loops and promises with closures using. I know about others ways to solve this task. Corresponding to this case, how to print value 'i' from the loop and button name from the promise by one string. – Volodymyr Nabok Sep 03 '15 at 16:11