How can this function be tested with vows?

108 Views Asked by At

How can the following function, intended to add routes to express.js app based on an object hierarchy, be tested using vows.js cleanly without breaking vows' separation of the topic and the vow?

var addRoutes = function(routeObject, app, path) {

    var httpVerbs = ['get', 'post', 'put', 'delete'];

    path = path || '';

    for(var property in routeObject){
        var routesAdded = false;
        for (var verbIndex in httpVerbs) {
            var verb = httpVerbs[verbIndex];
            var completePath, handler;
            if (property === verb) {
                if (typeof(routeObject[verb]) === 'function') {
                    handler = routeObject[verb];
                    completePath = path;
                } else {
                    handler = routeObject[verb].handler;
                    completePath = path + (routeObject[verb].params || '');
                }
                app[verb](completePath, handler);
                routesAdded = true;
            }
        }
        if (!routesAdded) {
            addRoutes(routeObject[property], app, path + '/' + property);
        }
    }
};

The test should confirm that functions corresponding to http verbs are called on the app object. e.g. if routeObject is:

{
    tracker: {
        message: {
            get: {
                handler: function (req, res) {
                    res.send("respond with a resource");
                }
            }
        }
    }

}

then

app.get('/tracker/message', function (req, res) {
                            res.send("respond with a resource");
                        });

should be called.

1

There are 1 best solutions below

1
On

Something like this should work:

var assert = require('assert'),
    request = require('request');

var verbs = ['get', 'post', 'put', 'delete'],
    app = require('your/app.js'),
    port = 8080;

//
// Your route would look something like this
//
var example = {
  tracker: {
    message: {
      get: {
        status: 200,
        body: 'respond with a resource'
      }
    }
  }
};

function testRoutes(suite, route, app, path) {
  path = path || '/';
  Object.keys(route).forEach(function (key) {
    if (~verbs.indexOf(key)) {
      return testRoutes(suite, route[key], app, [path, key].join('/'));
    }

    var test = [key, path].join(' ');
    suite[test] = {
      topic: function () {
        request({
          method: key,
          uri: 'http://localhost' + port + path
        }, this.callback);
      },
      'should respond correctly': function (err, res, body) {
        assert.isNull(err);
        assert.equal(res.statusCode, route[key].status);
        assert.equal(body, route[key].body);
      }
    }
  });

  return suite;
}

var suite = vows.describe('api');
testRoutes(suite, example, app);
suite.export(module);