Reto Ryter
Reto Ryter

Reputation: 51

Casper JS waitForResource with a restful API

We are having a little problem with a functional test with casper.js.

We request the same resource twice, first with the GET and then with POST method. Now when waiting for the second resource (POST) it matches the first resource and directly goes to the "then" function.

We would like to be able to check for the HTTP method in the "test" function, that way we can identify the resource properly. For now we use the status code (res.status), but that doesn't solve our problem fully, we really need the http method.

// create new email
this.click(xPath('//div[@id="tab-content"]//a[@class="button create"]'));

// GET
this.waitForResource('/some/resource', 
    function then() {
        this.test.assertExists(xPath('//form[@id="email_edit_form"]'), 'Email edit form is there');

        this.fill('form#email_edit_form', {
            'email_entity[email]': '[email protected]',
            'email_entity[isMain]': 1
        }, true);

        // POST
        this.waitForResource(
            function test(res) {
                return res.url.search('/some/resource') !== -1 && res.status === 201;
            },
            function then() {
                this.test.assert(true, 'Email creation worked.');
            },
            function timeout() {
                this.test.fail('Email creation did not work.');
            }
        );
    },
    function timeout() {
        this.test.fail('Email adress creation form has not been loaded');
    });

Or maybe there is a better way to test this scenario? Although since this is a functional test we need to keep all those steps in one test.

Upvotes: 5

Views: 2469

Answers (2)

elHornair
elHornair

Reputation: 432

The res parameter that is passed to the test function has an ID. I created a helper that tests against this ID and blacklists it, so the same resource won't get accepted a second time.

var blackListedResourceIds = [],
    testUniqueResource = function (resourceUrl, statusCode) {
        return function (res) {
            // check if resource was already loaded
            var resourceFound = res.url.search(resourceUrl) !== -1;

            // check statuscode
            if (statusCode !== undefined) {
                resourceFound = resourceFound && res.status === statusCode;
            }

            // check blacklisting
            if (!resourceFound || blackListedResourceIds[res.id] !== undefined) {
                return false;
            } else {
                blackListedResourceIds[res.id] = true;
                return true;
            }
        };
    };

Upvotes: 1

NiKo
NiKo

Reputation: 11412

You can try to alter the form action url to add some query string, therefore generating a new resource appended to the stack. Could be done this way:

casper.thenEvaluate(function() {
    var form = __utils__.findOne('#email_edit_form');
    form.setAttribute('action', form.getAttribute('action') + '?plop');
});

That's a hack though, and functional testing should never be achieved that way. Let's hope more information will be added to the response objects in the future.

Upvotes: 1

Related Questions