CasperJS waitForResource again

696 views Asked by At

Im using

.waitForResource('/auth')
.then( .... )
.waitForResource('/auth')
.then( .... )

To wait for an ajax call to /auth to complete before then validating the UI response.

However, the subsequent call to /auth appear to continue immediately as it has already loaded that resource.

Is there some way to tell casperJS to wait again, or clear that resource so it doesn't think it has loaded for the second request?

2

There are 2 answers

0
Artjom B. On BEST ANSWER

Is there some way to tell casperJS to wait again, or clear that resource so it doesn't think it has loaded for the second request?

Yes, that's exactly what you can do. You can tell CasperJS to clear all the resources that it has previously seen by re-initializing the resources array:

casper.resources = [];

If you don't want to be that destructive, you can mimic the how the casper.resourceExists() function finds resources and remove only those:

casper.forgetResources = function(test){
    "use strict";
    this.checkStarted();
    var testFn,
        indexes = [],
        utils = require('utils');
    switch (utils.betterTypeOf(test)) {
        case "string":
            testFn = function _testResourceExists_String(res) {
                return res.url.search(test) !== -1 && res.status !== 404;
            };
            break;
        case "regexp":
            testFn = function _testResourceExists_Regexp(res) {
                return test.test(res.url) && res.status !== 404;
            };
            break;
        case "function":
            testFn = test;
            if (phantom.casperEngine !== "slimerjs")
                testFn.name = "_testResourceExists_Function";
            break;
        default:
            throw new CasperError("Invalid type");
    }

    this.resources.forEach(function(res, i){
        if (testFn(res)) {
            indexes.push(i);
        }
    });
    indexes = indexes.reverse();
    indexes.forEach(function(i){
        this.resources.splice(i, 1);
    });
    return this; // fluent API
};
casper.thenForgetResources = function(test){
    this.then(function(){
        this.forgetResources(test);
    });
    return this;
};

And you would use it like this:

.waitForResource('/auth')
.then( .... )
.thenForgetResources('/auth')
.waitForResource('/auth')
.then( .... )
0
Matt Bryson On

turns out it was working, I just needed a .wait(250) for the subsequent calls before the UI updated.

If anyone is interested I made a general method to capture all Ajax requests and enforce a 250ms wait, so you don't need to do

.waitForResource('/my/resource')
.wait(250)

Instead add this to your tests, or load it up as an include

/** 
 * Auto waitForResource on all Ajax requests.
 * Inserts a 250ms delay after load to allow any page renders with response   
 */
casper.options.onResourceRequested = function (casper, requestData){
    //is this Ajax..
    var isAjax = requestData.headers.some(function(header) {
        return (header.name == "X-Requested-With" && header.value == "XMLHttpRequest");
    });

    if(isAjax){
        casper.waitForResource(requestData.url, function(){
            casper.wait(250); //wait quarter of a sec for any page render after an ajax load...
        }, function(){
            console.error("AJAX request for " + requestData.url + " timed out.")
        }, 10000);
    }
}

And then it will auto wait for All ajax requests, and insert a 250ms delay for the UI to update.