0

I have an node / express js app that was generated using the yoman full stack generator. I have swapped out mongo / mongoose for cloudant db (which is just a paid for version of couchdb). I have a written a wrapper for the Cloudant node.js library which handles cookie auth with my instance via an init() method wrapped in a promise. I have refactored my application to not start the express server until the connection to the db has been established as per snippet below taken from my app.js

myDb.init(config).then(function (db) {
  logger.write(1001, '','Connection to Cloudant Established');
  // Start server
  server.listen(config.port, config.ip, function () {
    logger.write(1001, "",'Express server listening on '+config.port+', in '+app.get('env')+' mode');
  });
});

On my express routes I have introduced a new middleware which attaches the db object to the request for use across the middleware chain as per below. This gets the db connection object before setting the two collections to use.

exports.beforeAll = function (req, res, next) {
  req.my = {};

  // Adding my-db
  req.my.db = {};
  req.my.db.connection = myDb.getDbConnection();
  req.my.db.orders = req.my.db.connection.use(dbOrders);
  req.my.db.dbRefData = req.my.db.connection.use(dbRefData);
  next();
};

This mechanism works when i manually drive my apis through POSTman as the express server won't start until after the promise from the db connection has been resolved. However when running my automated tests the first few tests are now always failing because the application has not finished initialising with the db before jasmine starts to run my tests against the APIs. I can see in my logs the requests on the coming through and myDb.getDbConnection(); in the middleware returning undefined. I am using supertest and node-jasmine to run my tests. For example

'use strict';

var app = require('../../app');
var request = require('supertest');

describe('GET /api/content', function () {

  it('should respond with JSON object', function (done) {
    request(app)
      .get('/api/content')
      .expect(200)
      .expect('Content-Type', /json/)
      .end(function (err, res) {
        if (err) return done(err);
        expect(res.body).toEqual(jasmine.any(Object));
        done();
      });
  });
});

So, my question is how can I prevent supertest from making the requests until the server.listen() step has been completed as a result of the myDb.init() call being resolved? OR perhaps there is some kind of jasmine beforeAll that I can use to stop it running the describes until the promise has been resolved?

springdo
  • 43
  • 5

1 Answers1

1

You could make you app return an EventEmitter which emits a "ready" event when it has completed its initialisation.

Then your test code, in a before clause, can wait until the "ready" event arrives from the app before proceeding with the tests.

Glynn Bird
  • 5,507
  • 2
  • 12
  • 21
  • Thanks Glynn - this worked fine. It was easier to hook into the ExpressJS event emitter than the Node one for anyone looking to this answer in the future! – springdo Mar 05 '16 at 20:11