Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting text of more then one element #123

Closed
filidorwiese opened this issue Dec 16, 2013 · 5 comments
Closed

Getting text of more then one element #123

filidorwiese opened this issue Dec 16, 2013 · 5 comments

Comments

@filidorwiese
Copy link

Using .getText() I can get the text of an element by css-selector. However, there seems to be no simple way of getting the text of multiple elements in an array. For example:

client.getTexts('.cities', function(err, cities){
     // cities would be an array of texts found in the .cities elements
});

Another approach I was playing with is to use a for loop:

var cities = [];
for (var i = from; i < to; i++) {
    client.getText('.cities', function(err, city){
        cities.push(city);
        if (i === to) { callback(cities); }
    });
}

Sadly this doesn't work either (i is always 4 because of the way closures work). Is there some way to accomplish what I need?

@christian-bromann
Copy link
Member

Try something like this:

client.elements('css selector', '.cities', function(err,res){
    res.value.ELEMENT.forEach(function(elemID) {
        client.elementIdText(elemID,function(err,res) {
             console.log(res.value);
        });
    });
});

At the moment the most of the implemented commands are using the element protocol command to fetch one element in the page. This will change in near future. In the example above, you will fetch all elements matching the css selector .cities. You'll get an array with element IDs (something like [1,2,3,4,5,...]). Each ID represents one element on the page with given css selector. Then you just have to iterate through the array and call the protocol command of getText.

Like I said the possibility to get results of multiple elements will be implemented in WebdriverJS soon. I will file a pull request probably this week.

Is this helping you? Let me know if you have any problems!

@filidorwiese
Copy link
Author

Hi Christian, thanks for your quick reply! It doesn't seem to be working. The problem is that .elementIdText() is also asynchronous. To illustrate, the following code:

var from = 0, to = 3, cities = [];
client.elements('css selector', '.cities', function(err, results) {
    for (var i = from; i < to; i++) {
        this.elementIdText(results.value[i].ELEMENT, function(err, result) {
            cities.push(result.value);
        });
    }
});
callback(cities);

results in the callback getting called with an empty array even before the for loop has started. Will something like this be possible with the improvements you're planning to push?

@christian-bromann
Copy link
Member

You need to call the callback function after all elementIdText commands ran. To do so use the call function from WebdriverJS like this:

var from = 0, to = 3, cities = [];
client
    .elements('css selector', '.cities', function(err, results) {
        for (var i = from; i < to; i++) {
            this.elementIdText(results.value[i].ELEMENT, function(err, result) {
                cities.push(result.value);
            });
        }
    })
    .call(callback.bind(this,cities));

With the improvements I planned you could use getText like before but would get an array of results back. Much more easier to handle.

@vvo
Copy link

vvo commented Dec 16, 2013

Use a control flow lib to do that, like async.map.

// Callback called with err, [cities]
// ...
async.map(results.value, function(res, cb) {
  client.elementIdText(res.ELEMENT, function(err, result) {
    cb(result.value)
  })
}, callback);

@filidorwiese
Copy link
Author

I'm afraid that the solution Christian offers doesn't work, I'm getting the first found city element on the page back three times (I suspect it's because the for loop is synchronous but the .elementIdText() isn't). The async solution did work however. Thank you both for helping me out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants