A suite to track Project Diva score statistics and ratings / D4DJ event data.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
projectdivar/server/node_modules/express-promise-router/test/express-promise-router.test.js

401 lines
9.3 KiB

"use strict";
var assert = require("chai").assert;
var sinon = require("sinon");
var express = require("express");
var GET = require("./util/http-utils").GET;
var delay = function (method, payload) {
setTimeout(function () {
method(payload);
}, 10);
};
var PromiseRouter = require("../lib/express-promise-router.js");
describe("express-promise-router", function () {
var app;
var serverListening;
var server;
var router;
var bootstrap = function (router) {
app = express();
app.use("/", router);
if (serverListening) {
throw "already bootstrapped";
}
serverListening = new Promise(function (resolve, reject) {
server = app.listen(12345, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
return serverListening;
};
beforeEach(function () {
router = new PromiseRouter();
});
afterEach(function () {
if (serverListening) {
return serverListening.then(function () {
server.close();
app = undefined;
server = undefined;
serverListening = undefined;
});
}
});
it("should call next with an error when a returned promise is rejected", function () {
var callback = sinon.spy();
router.use("/foo", function () {
return new Promise(function (resolve, reject) {
delay(reject, "some error");
});
});
router.use(function (err, req, res, next) {
assert.equal("some error", err);
callback();
res.send();
});
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function () {
assert(callback.calledOnce);
});
});
it('should call next without an error when a returned promise is resolved with "next"', function () {
var errorCallback = sinon.spy();
var nextCallback = sinon.spy();
router.use("/foo", function () {
return new Promise(function (resolve) {
delay(resolve, "next");
});
});
router.use("/foo", function (req, res) {
nextCallback();
res.send();
});
router.use(function (err, req, res, next) {
errorCallback();
next();
});
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function () {
assert(errorCallback.notCalled);
assert(nextCallback.calledOnce);
});
});
it('should not call next when a returned promise is resolved with anything other than "route" or "next"', function () {
var callback = sinon.spy();
router.get("/foo", function (req, res) {
return new Promise(function (resolve) {
res.send();
delay(resolve, "something");
});
});
router.get("/bar", function (req, res) {
return new Promise(function (resolve) {
res.send();
delay(resolve, {});
});
});
router.use(function (req, res) {
callback();
res.send(500);
});
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function () {
assert(callback.notCalled);
return GET("/bar");
})
.then(function () {
assert(callback.notCalled);
});
});
it("should move to the next middleware when next is called without an error", function () {
var callback = sinon.spy();
router.use("/foo", function (req, res, next) {
next();
});
router.use("/foo", function (req, res, next) {
callback();
res.send();
});
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function () {
assert(callback.calledOnce);
});
});
it("should move to the next error handler when next is called with an error", function () {
var callback = sinon.spy();
var errorCallback = sinon.spy();
router.use("/foo", function (req, res, next) {
next("an error");
});
router.use("/foo", function (req, res, next) {
callback();
next();
});
router.use(function (err, req, res, next) {
assert.equal("an error", err);
errorCallback();
res.send();
});
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function () {
assert(errorCallback.calledOnce);
assert(callback.notCalled);
});
});
it("should call chained handlers in the correct order", function () {
var fn2 = sinon.spy(function (req, res) {
res.send();
});
var fn1 = sinon.spy(function () {
assert(fn2.notCalled);
return Promise.resolve("next");
});
router.get("/foo", fn1, fn2);
return bootstrap(router).then(function () {
return GET("/foo");
});
});
it("should correctly call an array of handlers", function () {
var fn2 = sinon.spy(function (req, res) {
res.send();
});
var fn1 = sinon.spy(function () {
assert(fn2.notCalled);
return Promise.resolve("next");
});
router.get("/foo", [[fn1], [fn2]]);
return bootstrap(router).then(function () {
return GET("/foo");
});
});
it('should call next("route") if a returned promise is resolved with "route"', function () {
var fn1 = function () {
return Promise.resolve("route");
};
var fn2 = function () {
assert.fail();
};
router.get("/foo", fn1, fn2);
router.get("/foo", function (req, res) {
res.send();
});
return bootstrap(router).then(function () {
return GET("/foo");
});
});
it("should bind to RegExp routes", function () {
var fn1 = function (req, res) {
res.send();
};
router.get(/^\/foo/, fn1);
return bootstrap(router).then(function () {
return GET("/foo");
});
});
it('multiple calls to handlers that have used "next" should not interfere with each other', function () {
var fn = sinon.spy(function (req, res, next) {
if (fn.calledOnce) {
next("error");
} else {
setTimeout(function () {
res.status(200).send("ok");
}, 15);
}
});
var errHandler = function (err, req, res, next) {
if (err === "error") {
res.send("fail");
} else {
next(err);
}
};
router.get("/foo", fn, errHandler);
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function (res) {
assert.equal(res.body, "fail");
return GET("/foo");
})
.then(function (res) {
assert.equal(res.body, "ok");
});
});
it("calls next if next is called even if the handler returns a promise", function () {
var fn = function (req, res, next) {
next();
return new Promise(function (resolve, reject) {});
};
var fn2 = function (req, res) {
res.send("ok");
};
var errHandler = function (err, req, res, next) {
res.send("error");
};
router.get("/foo", fn, fn2, errHandler);
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function (res) {
assert.equal(res.body, "ok");
});
});
it("calls next with an error if the returned promise is rejected with no reason", function () {
var fn = function () {
return new Promise(function (resolve, reject) {
delay(reject, null);
});
};
var errHandler = function (err, req, res, next) {
res.send("error");
};
router.get("/foo", fn, errHandler);
return bootstrap(router)
.then(function () {
return GET("/foo");
})
.then(function (res) {
assert.equal(res.body, "error");
});
});
it("should handle resolved promises returned in req.param() calls", function () {
router.param("id", function () {
return new Promise(function (resolve) {
delay(resolve, "next");
});
});
router.use("/foo/:id", function (req, res) {
res.send("done");
});
return bootstrap(router)
.then(function () {
return GET("/foo/1");
})
.then(function (res) {
assert.equal(res.body, "done");
});
});
it("should call next with unresolved promises returned in req.param() calls", function () {
var assertOutput = "error in param";
router.param("id", function (req, res, next, id) {
return new Promise(function (resolve, reject) {
delay(reject, assertOutput);
});
});
var fn = function (req, res) {
res.send("done");
};
var errHandler = function (err, req, res, next) {
res.send(err);
};
router.use("/foo/:id", fn);
router.use(errHandler);
return bootstrap(router)
.then(function () {
return GET("/foo/1");
})
.then(function (res) {
assert.equal(res.body, assertOutput);
});
});
it("support array in routes values", function () {
router.use(["/", "/foo/:bar"], function (req, res) {
res.send("done");
});
return bootstrap(router)
.then(function () {
return GET("/");
})
.then(function (res) {
assert.equal(res.body, "done");
return GET("/foo/1");
})
.then(function (res) {
assert.equal(res.body, "done");
});
});
it("should throw sensible errors when handler is not a function", function () {
assert.throws(function () {
router.use("/foo/:id", null);
}, /callback/);
});
});