I'm writing a Protractor test that has to wait for an element attribute to have a non-empty value and then I want to return that value to the caller function. This has proven to be more difficult to write than I expected!
I am able to correctly schedule a browser.wait()
command to wait for the element attribute to have a non-empty value and I have verified that this value is in fact what I am expecting to get inside the callback function, but for some reason, I am not able to return that value outside of the callback function and onto the rest of the test code.
Here is how my code looks like:
function test() {
var item = getItem();
console.log(item);
}
function getItem() {
var item;
browser.wait(function() {
return element(by.id('element-id')).getAttribute('attribute-name').then(function(value) {
item = value;
// console.log(item);
return value !== '';
});
});
return item;
}
I can tell that the order of execution is not as I expect it to be, because when I uncomment the console.log()
call inside the callback function, I see the expected value printed out. However, the same call in the test()
function prints 'undefined'.
What is going on here? What am I missing? How can I get the attribute value out of the callback function properly?
I appreciate your help.
I'm writing a Protractor test that has to wait for an element attribute to have a non-empty value and then I want to return that value to the caller function. This has proven to be more difficult to write than I expected!
I am able to correctly schedule a browser.wait()
command to wait for the element attribute to have a non-empty value and I have verified that this value is in fact what I am expecting to get inside the callback function, but for some reason, I am not able to return that value outside of the callback function and onto the rest of the test code.
Here is how my code looks like:
function test() {
var item = getItem();
console.log(item);
}
function getItem() {
var item;
browser.wait(function() {
return element(by.id('element-id')).getAttribute('attribute-name').then(function(value) {
item = value;
// console.log(item);
return value !== '';
});
});
return item;
}
I can tell that the order of execution is not as I expect it to be, because when I uncomment the console.log()
call inside the callback function, I see the expected value printed out. However, the same call in the test()
function prints 'undefined'.
What is going on here? What am I missing? How can I get the attribute value out of the callback function properly?
I appreciate your help.
Share Improve this question edited Jan 23, 2016 at 16:31 exbuddha asked Jan 23, 2016 at 8:15 exbuddhaexbuddha 6331 gold badge9 silver badges19 bronze badges2 Answers
Reset to default 14I would not combine the wait and the getting attribute parts - logically these are two separate things, keep them separate:
browser.wait(function() {
return element(by.id('element-id')).getAttribute("attribute").then(function(value) {
item = value;
// console.log(item);
return value !== '';
});
});
element(by.id('element-id')).getAttribute("attribute").then(function (value) {
console.log(value);
});
Note that, you may simplify the wait condition this way:
var EC = protractor.ExpectedConditions;
var elm = $('#element-id[attribute="expected value"]');
browser.wait(EC.presenceOf(elm), 5000);
elm.getAttribute("attribute").then(function (value) {
console.log(value);
});
Just FYI, you may have solved your current problem with the deferred
:
function test() {
getItem().then(function (value) {
console.log(value);
});
}
function getItem() {
var item = protractor.promise.defer();
browser.wait(function() {
return element(by.id('element-id')).getAttribute('attribute').then(function(value) {
var result = value !== '';
if (result) {
item.fulfill(value);
}
return result;
});
});
return item.promise;
}
After doing some more reading about how protractor works with promises and schedules/registers them with the control flow, I found an easier work-around close to the first solution @alecxe provided. Here it goes:
function test() {
var item = getItem().then(function(item) {
console.log(item);
});
}
function getItem() {
return browser.wait(function() {
return element(by.id('element-id')).getAttribute('attribute-name').then(function(value) {
return value;
});
});
}
Since browser.wait()
returns a promise itself, it can be chained with another then()
inside the caller and this way the right order of execution is guaranteed.