0

I am trying to set up testing in-browser using Mocha 2.4.5 and Should.js 8.3.0.

Failing Should assertions display a useful test failure reason.
However, when that same assertion is made in the context of a jQuery Ajax callback, I get an Uncaught Assertion Error instead.

Take the following example:

mocha.setup('bdd');
var url = 'http://localhost/api/v2/People';
describe('ajax', () => {
    var that1 = this;
    it('Passing async assertion', (done) => {
        $.ajax({ url: url }).done(data => {
            should(1).be.eql(1);
            done();
        });
    });
    it('Failing async assertion', (done) => {
        var that2 = this;
        $.ajax({ url: url }).done(data => {
            should(0).be.eql(1);
            done();
        });
    });
    it('Failing sync assertion', (done) => {
        should(0).be.eql(1);
        done();
    });
});
mocha.run();

'Passing async assertion' passes and looks pretty in the test runner output.

'Failing sync assertion' fails and I get a useful stacktrace

Fail sync assertion ‣
AssertionError: expected 0 to equal 1
at Assertion.fail (http://path/to/should.js:220:17)
at Assertion.Object.defineProperty.value (http://path/to/should.js:292:19)
at Context. (tests.js:337:26)

However, 'Failing async assertion' fails (which is fine), but the stacktrace is usless.

Fail async assertion ‣
Error: Uncaught AssertionError (http://path/to/should.js:200)

I've played around with setting the ajax context to that1 or that2, but it makes no difference.

Is there some other way to format the test cases so asynchronous assertions work?

EDIT

I get the same thing using a simple timeout to simulate the asynchronicity

mocha.setup('bdd');
describe('ajax', () => {
    var that1 = this;
    it('Failing async assertion', (done) => {
        setTimeout(() => {
            should(0).be.eql(1);
            done();
        }, 100);
    }).async = true;
    it('Failing sync assertion', (done) => {
        should(0).be.eql(1);
        done();
    });
});
mocha.run();
Silver Solver
  • 2,310
  • 1
  • 13
  • 19

1 Answers1

0

The docs for Mocha suggest formatting asynchronous tests as I have in my question, but I think those docs are written with the Node.js test runner in mind.

In the browser, it appears that it is necessary to execute asynchronous code in the 'before' function, and then make synchronous assertions based on a stored value.

For example:

mocha.setup('bdd');
describe('ajax', () => {
    var value = 0;
    before((done) => {
        //Do the asynchronous bit
        setTimeout(() => {
            //store the value for later comparison
            value = 1;
            done();
        }, 100);
    });
    //These wont be called until after done() is called above.
    //So value will be 1
    it('Failing assertion', () => {
        should(value).be.eql(0);
    });
    it('Passing assertion', () => {
        should(value).be.eql(1);
    });
});
mocha.run();

The added benefit here is that Mocha wont flag the async assertions as slow due to external factors (like network latency).

Silver Solver
  • 2,310
  • 1
  • 13
  • 19