Skip to content

Wait for mocked XHR to fulfil all requests #71

@serbanghita

Description

@serbanghita

I'm having the following situation:

function reloadApp() {
   $.ajax({url: "first/url"}).then(() => {

       $.ajax({url: "second/url"}).then(() => updateSomeDOMAttributes());

   }).then((r1) => addSomeDOMAttributes());

   renderDOMComponent();
}

There are two ajax requests nested but not chained to one another.
I'm using Sinon.js (which uses nise).

I have no way of waiting for the second request to fulfil unless I chain the Promise which is something I cannot do without breaking compatibility (let's assume that it cannot be done).

    beforeEach(() => {
        server = sinon.createFakeServer({respondImmediately: true});
        spy = sinon.spy(tracking, "trackEvent");
    });

    afterEach(() => {
        server.restore();
        spy.restore();
    });

    it('ajax mocking works #1', (done) => {
    
         server.respondWith("GET", 'first/url', [ 200, { "Content-Type": "text/html" }, `mocked1` ]);
         server.respondWith("GET", 'second/url', [ 200, { "Content-Type": "text/html" }, `mocked2` ]);
    
         reloadApp().then((r1) => {
             expect(r1).to.equal(`mocked1`);
             expect(spy.callCount).to.equal(2); <------- fails
             done();
         });
    
         // server.respond();
    
     });

I tried both strategies with respondImmediately and with the server.respond().

My solution is to make a helper:

/**
 * Wait for the Sinon.js nise XHR mocks to finish their registered
 * responses.
 *
 * @param server Server created with sinon.createFakeServer
 * @param timeout Optional, how much to wait before failing.
 * @returns {Promise<any>}
 */
function waitForServerToFulfillRequests(server, timeout) {
    timeout = timeout || 100;
    return new Promise((resolve, reject) => {
        let checkCount = 0;
        const i = setInterval(() => {
            if (server.requests.length === server.responses.length) {
                clearInterval(i);
                resolve();
            }
            if (checkCount === 100) {
                clearInterval(i);
                reject(`Maximum waiting count of ${checkCount * 16} has passed.`);
            }
            checkCount++;
        }, 16);
    });
}

This is obviously an edge case but my goal is to test the final outcome of the code and wait for all the requests to finish because they modify the HTML component that I'm testing.

Working example: https://github.com/serbanghita/karma-mocha-chai-sinon ;

Let me know your thoughts on the situation and waitForServerToFulfillRequests

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions