diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..21489be --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,77 @@ +module.exports = function(grunt) { + 'use strict'; + + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + jshint: { + options: { + indent : 2, + maxlen : 80, + node : true, + eqeqeq : true, + latedef : true, + noarg : true, + noempty : true, + plusplus : true, + quotmark : true, + undef : true, + unused : true, + strict : true, + trailing : true + }, + + srcFiles : { + src : ['Gruntfile.js', 'index.js'] + }, + + testFiles : { + options : { + expr : true, + globals : { + describe : true, + it : true, + after : true, + before : true, + afterEach : true, + beforeEach : true, + expect : true + } + }, + src : ['test/parameters.js'] + } + }, + + mochaTest: { + test: { + options: { + require : ['test/setup.js'], + reporter: 'dot', + ui: 'bdd', + ignoreLeaks: false + }, + src: ['test/**/*.js'] + } + } + }); + + + // Load the jshint plugin + grunt.loadNpmTasks('grunt-contrib-jshint'); + + // Load the mocha runner plugin + grunt.loadNpmTasks('grunt-mocha-test'); + + + // Test tasks + grunt.registerTask('test', [ + 'jshint:srcFiles', + 'jshint:testFiles', + 'mochaTest' + ]); + + // Default task(s). + grunt.registerTask('default', ['test']); + +}; diff --git a/test/parameters.js b/test/parameters.js new file mode 100644 index 0000000..90788b4 --- /dev/null +++ b/test/parameters.js @@ -0,0 +1,178 @@ +(function () { + 'use strict'; + + var expect = require('chai').expect; + var sinon = require('sinon'); + + var parameters = require('../'); + + + describe('parameters-middleware', function () { + it('is accessible', function () { + expect(parameters).to.be.defined; + }); + + + it('is a function', function () { + expect(parameters).to.be.a('function'); + }); + + + it('throws an error if no params are specified', function () { + function withoutParams() { + parameters(); + } + + var message = 'Missconfigured: no required parameters set'; + expect(withoutParams).to.throw(message); + }); + + + it('returns a middleware', function () { + var middleware = parameters({ + query : ['foo', 'bar'] + }); + + expect(middleware).to.be.a('function'); + expect(middleware).to.have.length(3); + }); + + + describe('middleware', function () { + var req; + var res; + var next; + + before(function () { + req = { + query : { + foo : 'foobar' + }, + body : { + bar : 'barbaz' + }, + custom : { + baz : 'bazfoo' + } + }; + + res = { + send : sinon.spy() + }; + + next = sinon.spy(); + }); + + + beforeEach(function () { + res.send.reset(); + next.reset(); + }); + + + it('calls the next middleware if all parameters are set', function () { + var middleware = parameters({ + query : ['foo'], + body : ['bar'], + custom : ['baz'] + }); + + middleware(req, res, next); + + expect(next).to.have.been.calledOnce; + }); + + + it('does not call the next middleware if a param is missing', + function () { + var middleware = parameters({ + query : ['missing'] + }); + + middleware(req, res, next); + + expect(next).not.to.have.been.called; + }); + + + it('responds with a status 400 (bad request) if params are missing', + function () { + var middleware = parameters({ + query : ['missing'] + }); + + middleware(req, res, next); + expect(res.send).to.have.been.calledWith(400); + }); + + + it('uses the configured message', function () { + var params = { + query : ['missing'] + }; + + var options = { + message : 'Custom message' + }; + + var middleware = parameters(params, options); + + middleware(req, res, next); + + var message = res.send.lastCall.args[1]; + expect(message).to.equal(options.message); + }); + + + it('allows to use a message function', function () { + var params = { + query : ['missing'] + }; + + var options = { + message : function (missing) { + return 'Missing params: ' + missing.join(', '); + } + }; + + var middleware = parameters(params, options); + + middleware(req, res, next); + + var message = res.send.lastCall.args[1]; + var expected = 'Missing params: missing'; + expect(message).to.equal(expected); + }); + + + it('checks arbitrary properties in the request', function () { + var params = { + // Usually, there's no 'custom' property in the request object + custom : ['baz'] + }; + + var middleware = parameters(params); + + middleware(req, res, next); + expect(next).to.have.been.called; + }); + + + it('respects the property in which each param should be found', + function () { + var params = { + // The request has 'foo' in the query and 'bar' in the body, + // this should fail... + query : ['bar'], + body : ['foo'] + }; + + var middleware = parameters(params); + + middleware(req, res, next); + expect(next).not.to.have.been.called; + expect(res.send).to.have.been.called; + }); + }); // middleware + }); // parameters-middleware +})(); diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 0000000..725d63f --- /dev/null +++ b/test/setup.js @@ -0,0 +1,13 @@ +/** + * Setup code for the test environment. + */ + +/** Sets sinon-related assertions into Chai's should and expect APIs. */ +(function () { + 'use strict'; + + var chai = require('chai'); + var sinonChai = require('sinon-chai'); + + chai.use(sinonChai); +})();