I\'m trying to write a function (using WebdriverJS lib) that iterates through a list of elements, checks the names and build an xpath locator that corresponds to that name.
Here you go, I cleaned it up a bit. This will actually return an error if one is experienced in the nested promises:
var findCreatedTask = function() {
var Promise = require('bluebird');
var createdTask;
return driver.findElements(By.xpath("//div[@id='Tasks_Tab']"))
.then(function(tasks) {
return Promise.map(tasks, function(task){
return driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText()
}).then(function(taskTitles){
for (let i = 0; i < taskTitles.length; i++){
if(taskTitles[i] === 'testName'){
createdTask = "//div[@id='Tasks_Tab'][" + i + "]";
return createdTask;
}
}
});
});
};
You call it using
findCreatedTask.then(function(res){
//do your thing
}).catch(function(err){
console.error(err.stack);
});
You could first get all the texts with promise.map
and then get the position with indexOf
:
var map = webdriver.promise.map;
var findCreatedTask = function() {
var elems = driver.findElements(By.xpath("//div[@id='Tasks_Tab']//div[@class='task-title']"));
return map(elems, elem => elem.getText()).then(titles => {
var position = titles.indexOf("testName") + 1;
return "//div[@id='Tasks_Tab'][" + position + "]";
});
}
You will not be able to return the value that you want from this function because when this function returns, the value is not defined yet.
This is not a problem that you try to return the value in the wrong place, but that you try to access it at the wrong time.
You have two options: you can either return a promise from this function, or this function can take a callback that would be called when the value is available.
This is not tested but should give you an idea on how to think about it.
Version with promise:
var findCreatedTask = function (callback) {
var createdTask;
return new Promise(function (resolve, reject) {
driver.findElements(By.xpath("//div[@id='Tasks_Tab']")).then(function(tasks) {
for (let index = 1; index <= tasks.length && !createdTask; index++) {
driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText().then(function(taskTitle) {
if (taskTitle == "testName") {
createdTask = "//div[@id='Tasks_Tab'][" + index + "]";
resolve(createdTask);
}
});
}
});
});
};
and then you call it with:
findCreatedTask().then(function (createdTask) {
// you have your createdTask here
});
Version with callback:
var findCreatedTask = function (callback) {
var createdTask;
driver.findElements(By.xpath("//div[@id='Tasks_Tab']")).then(function(tasks) {
for (let index = 1; index <= tasks.length && !createdTask; index++) {
driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText().then(function(taskTitle) {
if (taskTitle == "testName") {
createdTask = "//div[@id='Tasks_Tab'][" + index + "]";
callback(null, createdTask);
}
});
}
});
};
and then you call it with:
findCreatedTask(function (err, createdTask) {
// you have your createdTask here
});
You can read some other answers that explain how promises and callbacks work if you're interested to know ore about it: