9

I'm using Jasmine 2.3 installed via NPM and executed with Grunt.

'use strict';

module.exports = function(grunt) {
    grunt.initConfig({
        package: grunt.file.readJSON('package.json'),
        exec: {
            jasmine: 'node_modules/.bin/jasmine'
        }
    });
    require('load-grunt-tasks')(grunt);
    require('time-grunt')(grunt);
    grunt.registerTask('default', 'exec:jasmine');
};

I exported an Express.js application object and using it in my specs along with SuperTest.

'use strict';

var supertest = require('supertest')
var application = require('../../../../../server');

describe('GET /api/users', function() {
    it('should respond with json', function(done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, done);
    });
});

When I run the spec I get no errors even though a 200 status code was expected and 404 was the result. Is the problem in Jasmine or SuperTest, or maybe I should be using SuperAgent.

I have no routes setup just a 404 error handler setup on the Express application object.

application.use(function(request, response, next) {
    response
        .status(404)
        .send({
            message: 'not found'
        });
});
Zorin Greene
  • 197
  • 4
  • 11
  • SuperTest uses SuperAgent internally I believe, so that shouldn't be the issue. How are you verifying that the response is a `404`? Could you show us some code from your router? – Brennan May 13 '15 at 18:58
  • No router is setup, just a 404 error handler. – Zorin Greene May 13 '15 at 19:13

3 Answers3

11

Firstly, Good question! I've learned some things researching this. Apparently Jasmine + Supertest don't play very well together. The reason for this appears to be Supertest calling done(err), but Jasmine will only fail when done.fail() or fail() is called. You can see some github issues here, and here.

Use this code to see proof:

describe('GET /api/users', function() {
    it('should respond with json', function(done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, function(res){
              console.log(res); 
              //res is actually an error because supertest called done(error)!
              done.fail() //Now jasmine will actually fail
            });
    });
});

Given this, it appears the easiest solution is to use an alternate library that play nicely together. I've personally used mocha instead of jasmine, and had good success. The choice is yours!

If you really wanted to, you could use jasmine and write your own validators seen in the supertest documentation here.

I hope this helps!

Brennan
  • 1,764
  • 1
  • 14
  • 17
3

The reason for test failure is because of Supertest calling done(err) whereas Jasmine fails on done.fail() or fail(). Despite this, there is a way to make Jasmine and Supertest work together.

Check this out:

describe('GET /api/users', function() {
  it('should respond with json', function(done) {

    supertest(application)
      .get('/api/users')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(err, res) {

        if (err) {

          done.fail(err);

        } else {

          done();
        }
      });
  });
});

The addition of

.end(function(err, res) {

  if (err) {

    done.fail(err);

  } else {

     done();
  }
});

in the end of all Supertests within a describe block should resolve issues between Supertest and Jasmine. This will also provide some sweet error descriptions within the console.

datatype_void
  • 433
  • 5
  • 23
  • 1
    Looks like it doesn't fix issue with supertest + jasmine-node version2.0 brunch. 'err' param provided to callback is bad (sort of empty Object). – bFunc Nov 05 '15 at 12:06
  • This doesn't work for me using supertest-as-promised and jasmine 2. – reutsey Jan 20 '16 at 19:42
  • 1
    Adding the `.end(function(){})` callback with fixes the issue. It also prints a good error description as @datatype_void mentioned. ```Failures: 1) Application Route GET / should return http status 200 Message: Failed: expected 201 "Created", got 200 "OK" Stack: Error: expected 201 "Created", got 200 "OK"```. It also gives you an opportunity to use some good assertion library like Chai. – Mr. Doomsbuster Sep 10 '17 at 21:47
3

In order to avoid writing the logic in every .end() function. I suggest to use the following snippet before all your jasmine specs (or you can put it in a helper file helpers/tell-jasmine.js if you like):

function tellJasmine(done) {
    return function (err) {
        if (err) {
            done.fail(err);
        } else {
            done();
        }
    };
}


Now you can write .end(tellJasmine(done)) at the end of your supertest:

describe('GET /api/users', function () {
    it('should respond with json', function (done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200)
            .end(tellJasmine(done));
    });
});

Credit for this code goes to nesQuick.

nashwaan
  • 233
  • 2
  • 12