Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sails js running tests

I am trying to run my sails unit tests (using mocha and istanbul)

when running

grunt test

I get the errors

  1) "before all" hook
  2) "after all" hook

  0 passing (5s)
  2 failing

  1)  "before all" hook:
     Error: timeout of 2000ms exceeded
      at null.<anonymous> (/vagrant/node_modules/mocha/lib/runnable.js:157:19)
      at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)

  2)  "after all" hook:
     ReferenceError: sails is not defined

the setup does not seem to find my Sails...but doing

which sails

I get

/usr/local/node/node-default/bin/sails

and running sails lift works fine

Here is the mocha tests file in my project

//boostrap.test.js
var Sails = require('sails');

before(function(done) {
  Sails.lift({
    // configuration for testing purposes
  }, function(err, sails) {
    if (err) return done(err);
    // here you can load fixtures, etc.
    done(err, sails);
  });
});

after(function(done) {
  // here you can clear fixtures, etc.
  sails.lower(done);
});
like image 635
Confidence Avatar asked Oct 10 '14 13:10

Confidence


3 Answers

First, you have a typo issue, you have :

var Sails = require('sails');

But you try to use

sails.lower(done);

Instead of

Sails.lower(done);

Then, you need to define a project-wide "migrate" setting configured (http://sailsjs.org/#/documentation/concepts/ORM/model-settings.html?q=migrate) You just have to edit the config/models.js file. You can simply uncomment the following line :

//migrate: 'alter'

Enjoy :)

like image 99
Jean-Baptiste Avatar answered Oct 13 '22 19:10

Jean-Baptiste


I haven't seen the actual code of your test case, so I just list a couple of possibilities here.

If you run your test asynchronously, I think you need to set the timeout attribute in mocha to some number bigger. I wrote three very simple test cases, but I always get the same problem as you described. I have tried 10000ms, 20000ms and 30000ms. When I increase it to 90000ms, all the test cases are passed. So I think it's because sails really need some time to lift before the test begins.

Another thought is that have you set the 'migrate' attribute in your environment configuration file? If not, sails lift command will wait for your input to select "drop","alter" or "safe" before proceed, which will also cause the timeout problem in test.

like image 2
afterglowlee Avatar answered Oct 13 '22 18:10

afterglowlee


Its not like that I know your problem but it might help you find out yours if I write down some snipets of my working tests in sails. I am including the package.json file as well so that you know my version of each module.

here is the relevant modules in package.json:

rootproject/test/mocha.opts , this probably what u need

--timeout 5000

rootproject/package.json

{
  ...
  "dependencies": {
    ...
    "sails": "0.9.7",
    "sails-disk": "~0.9.0",
    "sails-memory": "^0.9.1",
    "sails-mongo": "^0.9.7",
    ...
  },
  "devDependencies": {
    "mocha": "^1.20.1",
    "barrels": "^0.0.3",
    "supervisor": "^0.6.0"
  },
  "scripts": {
    "start": "node app.js",
    "debug": "node debug app.js",
    "test": "PORT=9999 NODE_ENV=test mocha -R spec -b --recursive"
  },
  "main": "app.js",
  ...
}

I have also added another model adapter to be used by the tests at rootproject/config/adapters.js

test: {
  module   : 'sails-memory'
},

rootproject/test/index.js

var assert = require('assert');
var Sails = require('sails');
var barrels = require('barrels');

var fixtures;

var userTest = require('./controllers/User.js');
//... other test controllers  ...

//in case you need different simulations per controller you could add a custom Response in your test controller and use them instead
var defaultCustomRequest = function(urlParams, bodyParams/*whatever else u need*/) {
  //simulates the sails request
  //create an object here, based on how u use the req object in your sails controllers
  //.eg
  return {
    params: urlParams,
    body: bodyParams
  };
}

//in case you need different simulations per controller or per method you could add multiple custom Responses in your test controller and use them instead
var defaultCustomResponse = function(expectedCode, dataExpecting/*whatever else u need*/) {
  //simulates the sails res which I was using like this: res.status(httpCode).json({somedata})
  //use the assert function here to validate 
  //.eg
  status: function (responseCode){
    assert(expectedCode === responseCode, 'Expected status is ' + expectedCode + ' but ' + responseCode + ' was returned.');
    return this;
  },
  json: function (responseData){
    //assert your responseData with your expectedData
    return this;
  }
  return this;
},
}

before(function (done) {
  // Lift Sails with test database
  Sails.lift({
    log: {
      level: 'error'
    },
    adapters: {
      default: 'test'
    }
  }, function(err, sails) {
    if (err)
      return done(err);
    // Load fixtures
    barrels.populate(function(err) {
      done(err, sails);
    });
    // Save original objects in `fixtures` variable
    fixtures = barrels.objects;
  });
});

// Global after hook
after(function (done) {
  //console.log('fixtures loaded: ' + JSON.stringify(fixtures));
  sails.lower(done);
});

describe('User', function() { userTest.run(fixtures, customRequest, customRespose); });
//or describe('User', function() { userTest.run(fixtures); });
//... other test controllers ...

rootproject/test/controllers/User.js

var assert = require('assert');

var UserController = require('../../api/controllers/UserController.js');

module.exports = {

  run: function(fixtures, customReq, customRes) {
    describe('create', function(customReq, customRes) {
      it ('should create a few user entries', function() {
        if (!customReq) customReq = {/*custom request for user create*/};
        if (!customRes) customRes = {/*custom response for user create*/};

       //call your controllers for testing here
       //.eg
       UserController.create(
        new req({},
               {email: '[email protected]', password: 'password'})
        ,new res(201,
                {email: '[email protected]', password: null});
       UserController.create(
        new req({},
               {email: '[email protected]', password: 'password'})
        ,new res(400,
                {error: true});
    );

      });
    });

    //... more guns
  }
};

As you can see on the package.json I used sails 0.9.7, therefore there might be needed additional changes for 0.10.x versions. .eg instead of config/adapters.js there are the config/models.js and config/connections.js that are used.

like image 1
Angelos Kyriakopoulos Avatar answered Oct 13 '22 19:10

Angelos Kyriakopoulos