protractor: Protractor hangs when returning ElementFinders or WebElements from `map()`
Test setup: Non - Angular page, with browser.ignoreSynchronization = true Browser: IE9 Protractor: 2.1.0 webdrivers up to date
Description: In the below code I am using element.all within Page Objects to find elements. When run the test will hang indefinitely. This happens when I try to assign a ElementFinder from the array to a member variable (so I can have reference for future use).
If I comment the following two lines then the tests will run to completion.
self.rowWebElement = el; // commenting this line will not hang
And
'RowWebElement': el.getWebElement(), // commenting this line will not hang
So why is it hanging?
Code:
var TablePage = function() {
this.uri = "http://www.w3schools.com/html/html_tables.asp";
this.open = function() {
browser.get(this.uri);
};
this.getPageResults = function() {
var self = this;
var rows = element.all(by.className('reference'));
this.results = rows.map(function(el, idx) {
console.log('Processing row');
self.rowWebElement = el; // commenting this line will not hang
var cols = el.all(by.tagName('td'));
return {
'Number': cols.get(0).getText(),
'First Name': cols.get(1).getText(),
'Last Name': cols.get(2).getText(),
'Points': cols.get(3).getText(),
'RowWebElement': el.getWebElement(), // commenting this line will not hang
'Index': idx
}
});
return this.results;
};
this.getRow = function(fName) {
var self = this;
var deferred = protractor.promise.defer();
var filtered = [];
self.results.then(function (grid) {
for (var i=0; i < grid.length; i++) {
var result = grid[i]['First Name'];
if (result == fName ) {
console.log('Row matching criteria :' + result);
filtered.push(grid[i]);
}
}
deferred.fulfill(filtered[0]);
});
return new TableRowObjectPromise(deferred.promise);
};
};
var TableRowObjectPromise = function (trPromise) {
// Wrap the promise
var self = this;
this.getValue = function(colName) {
return trPromise.then(function(tr) {
return tr[colName];
});
};
};
/** ----------------------------------------------------------------
* begining of test
*/
var tablePage = new TablePage();
// Tests begin
describe('Table page', function() {
beforeAll(function() {
browser.ignoreSynchronization = true
});
it('- goto table page', function() {
tablePage.open();
});
it('- get table row objects', function() {
var pr1 = tablePage.getPageResults();
var tr = tablePage.getRow('Eve');
});
});
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 2
- Comments: 34 (10 by maintainers)
We are also seeing this with v5.3.2, this is in an environment where we use the new async/await and control flow disabled.
By the way, here is the hotfix we are using in our tests: in
protractor.conf
file insideonPrepare
:Still seeing this with Protractor 5.1.2. @juliemr please reopen.
Same problem here. After playing a little - found short reproducible code
But with this - works fine:
Still seeing the hang on Protractor 4.0.14.
This is not good. Operations like map should not fail like this for basic use-cases.
Is there a reason why
map()
is usingwebdriver.promise.fullyResolve()
, instead ofwebdriver.promise.when()
?https://github.com/angular/protractor/blob/master/lib/element.ts#L519
I experimented with changing it to
when
and didn’t get any failures in the Protractor test suite.Needing to resolve every nested promise-like property of every mapped object does not seem like a common requirement. But mapping to an object with an ElementFinder field does seem like a common requirement. And I’m not sure why you would want the full resolution to happen automatically? It seems like very non-obvious API design.
I would contend that it is much better to remove the
fullyResolve()
call and fix this bug. If users need this behaviour, they can always callwebdriver.promise.fullyResolve()
themselves on whatever they intend to return from the map function.