waitFor does not work in nested then statement
See original GitHub issue@awlayton as per request I’m opening a new issue for this problem. The code I’m working on is scraping a protected resource and I can’t make the access info publicly known (though Alex should have the connection info). Essentially it’s an Angular site for vehicle management, some vehicles have pictures, some do not (depending on if there was damage reported). In the former case it takes less time to load a vehicle than the latter case, and thus I need to conditionally wait for img tags or not.
My environment: Linux host. NodeJS: v5.7.0 PhantomJS: v2.1.1 Horseman: v2.8.2
//Broken:
var Horseman = require('/home/automationScripts/node_modules/node-horseman');
var valueStore = {};
valueStore.loginURL = "";
valueStore.username = "";
valueStore.password = "";
valueStore.VIN = "";
new Horseman()
.userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
.viewport(1080, 1920)
.then(function(){
console.log("Opening Login Page");
})
.open(valueStore.loginURL)
.type('input#IDToken1', valueStore.username)
.type('input#IDToken2', valueStore.password)
.click('[name="Login.Submit"]')
.then(function(){
console.log("Logged in!");
console.log("Loading Search Page");
})
.waitForSelector('[ng-model="vm.searchCriteria.vins"]')
.waitForSelector('button[ng-click*="vm.search()"]')
.screenshot('horseSearchPage.png')
.type('[ng-model="vm.searchCriteria.vins"]', valueStore.VIN)
.click('button[ng-click*="vm.search()"]')
.then(function(){
console.log("Searched for vin!");
console.log("Returning results");
})
.waitForSelector('role="listitem"')
.evaluate(function(){
var hasPictures = !!$('.fa-camera');
$('[role="listitem"] [role="button"]:first').click(); //click on item
return hasPictures;
})
.then(function(hasPictures){
console.log("Has pictures: "+hasPictures);
return this.waitFor(function(hasPictures){
if(hasPictures){
return $('.image-viewer-thumbnails').length > 0; //wait for images to load
}else{
return $('[ng-include*="image-viewer.html"]').length > 0; //only wait for image container (this should be present even if there aren't images)
}
}, hasPictures, true);
})
.screenshot('vehicle.png') //no pictures are loaded
.then(function(){
console.log("Closing horseman!");
})
.close();
//Working:
var Horseman = require('/home/automationScripts/node_modules/node-horseman');
var valueStore = {};
valueStore.loginURL = "";
valueStore.username = "";
valueStore.password = "";
valueStore.VIN = "";
new Horseman()
.userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
.viewport(1080, 1920)
.then(function(){
console.log("Opening Login Page");
})
.open(valueStore.loginURL)
.type('input#IDToken1', valueStore.username)
.type('input#IDToken2', valueStore.password)
.click('[name="Login.Submit"]')
.then(function(){
console.log("Logged in!");
console.log("Loading Search Page");
})
.waitForSelector('[ng-model="vm.searchCriteria.vins"]')
.waitForSelector('button[ng-click*="vm.search()"]')
.screenshot('horseSearchPage.png')
.type('[ng-model="vm.searchCriteria.vins"]', valueStore.VIN)
.click('button[ng-click*="vm.search()"]')
.then(function(){
console.log("Searched for vin!");
console.log("Returning results");
})
.waitForSelector('role="listitem"')
.evaluate(function(){
var hasPictures = !!$('.fa-camera');
$('[role="listitem"] [role="button"]:first').click(); //click on item
return hasPictures;
})
.then(function(hasPictures){
console.log("Has pictures: "+hasPictures);
valueStore.hasPictures = hasPictures;
})
.waitFor(function(hasPictures){
if(hasPictures){
return $('.image-viewer-thumbnails').length > 0; //wait for images to load
}else{
return $('[ng-include*="image-viewer.html"]').length > 0; //only wait for image container (this should be present even if there aren't images)
}
}, valueStore.hasPictures, true)
.screenshot('vehicle.png') //pictures are loaded!
.then(function(){
console.log("Closing horseman!");
})
.close();
Issue Analytics
- State:
- Created 7 years ago
- Comments:5
Top Results From Across the Web
Promise.all does not wait for nested promise? - Stack Overflow
I tried to use Promise.all to add each statement as a Promise, but Promise.all never waits for the nested Promise to complete. Similar...
Read more >`waitFor` with nested `expect` timeout in v9 · Issue #898 - GitHub
Hey guys, I've been banging my head for hours following a migration to v9. I had some timeout issues with a waitFor and...
Read more >Conditions Task - Apache Ant
Conditions are nested elements of the <condition> and <waitfor> tasks. There are core conditions and custom conditions. Custom conditions are described in ...
Read more >Async Await JavaScript Tutorial – How to Wait for a Function to ...
Alright, so we know that JavaScript is synchronous and lazy. It doesn't want to do all of the work itself, so it farms...
Read more >Promises chaining - The Modern JavaScript Tutorial
A Promise keeps an internal state. It calls the handler wrapped in a try...catch block and stores the error. That is why asynchronous...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The
.waitFor*
actions will timeout after a certain period (based on thetimeout
constructor option).In v2 the chain would still continue after a timeout though. In v3, the Promise will reject on timeout stopping the actions (unless you have a
.catch
that handles the timeout).With debugging on I can see that horseman is waiting for the selector in both cases. It seems the version without the
.then
just waits slightly longer for some reason.The problem is the
<img>
being present does not mean the image is loaded. You need to wait for the tag to be present (which is what you are doing), and the image to be loaded. I changed the.waitFor()
as shown below.Secondly,
'role="listitem"'
is not a valid selector. I changed it to'[role="listitem"]'
, which seems like what you wanted.With the above two changes, the top code works for me. Please note, the setup I had was:
I have not tested my changes with horseman 2.8.2, but ideally you would just use v3 since it is out of beta now.