mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-23 22:11:09 +03:00
Merge pull request #1815 from ErisDS/more-tests
Error handling simplification & test improvements
This commit is contained in:
commit
a50f5e1b9d
@ -9,7 +9,7 @@ var _ = require('underscore'),
|
||||
// Paths for views
|
||||
defaultErrorTemplatePath = path.resolve(configPaths().adminViews, 'user-error.hbs'),
|
||||
userErrorTemplatePath = path.resolve(configPaths().themePath, 'error.hbs'),
|
||||
userErrorTemplateExists,
|
||||
userErrorTemplateExists = false,
|
||||
|
||||
ONE_HOUR_S = 60 * 60;
|
||||
|
||||
@ -17,9 +17,9 @@ var _ = require('underscore'),
|
||||
* Basic error handling helpers
|
||||
*/
|
||||
errors = {
|
||||
updateActiveTheme: function (activeTheme) {
|
||||
updateActiveTheme: function (activeTheme, hasErrorTemplate) {
|
||||
userErrorTemplatePath = path.resolve(configPaths().themePath, activeTheme, 'error.hbs');
|
||||
userErrorTemplateExists = undefined;
|
||||
userErrorTemplateExists = hasErrorTemplate;
|
||||
},
|
||||
|
||||
throwError: function (err) {
|
||||
@ -165,20 +165,7 @@ errors = {
|
||||
}
|
||||
|
||||
// We're not admin and the template doesn't exist. Render the default.
|
||||
if (userErrorTemplateExists === false) {
|
||||
return renderErrorInt(defaultErrorTemplatePath);
|
||||
}
|
||||
|
||||
// userErrorTemplateExists is undefined, which means we
|
||||
// haven't yet checked for it. Do so now!
|
||||
fs.stat(userErrorTemplatePath, function (err, stat) {
|
||||
userErrorTemplateExists = !err;
|
||||
if (userErrorTemplateExists) {
|
||||
return renderErrorInt();
|
||||
}
|
||||
|
||||
renderErrorInt(defaultErrorTemplatePath);
|
||||
});
|
||||
return renderErrorInt(defaultErrorTemplatePath);
|
||||
},
|
||||
|
||||
error404: function (req, res, next) {
|
||||
|
@ -114,7 +114,7 @@ function activateTheme(activeTheme) {
|
||||
expressServer.set('theme view engine', hbs.express3(hbsOptions));
|
||||
|
||||
// Update user error template
|
||||
errors.updateActiveTheme(activeTheme);
|
||||
errors.updateActiveTheme(activeTheme, config.paths().availableThemes[activeTheme].hasOwnProperty('error'));
|
||||
}
|
||||
|
||||
// ### ManageAdminAndTheme Middleware
|
||||
|
@ -39,7 +39,7 @@ describe('Admin Routing', function () {
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
// we initialise data, but not a user. No user should be required for navigating the frontend
|
||||
// we initialise data, but not a user.
|
||||
return testUtils.initData();
|
||||
}).then(function () {
|
||||
done();
|
||||
|
@ -1,102 +1,273 @@
|
||||
/*globals describe, beforeEach, it*/
|
||||
var testUtils = require('../utils'),
|
||||
should = require('should'),
|
||||
when = require('when'),
|
||||
sinon = require('sinon'),
|
||||
/*globals describe, before, beforeEach, afterEach, it*/
|
||||
var testUtils = require('../utils'),
|
||||
should = require('should'),
|
||||
when = require('when'),
|
||||
sinon = require('sinon'),
|
||||
express = require("express"),
|
||||
|
||||
// Stuff we are testing
|
||||
colors = require("colors"),
|
||||
errors = require('../../server/errorHandling'),
|
||||
colors = require("colors"),
|
||||
errors = require('../../server/errorHandling'),
|
||||
// storing current environment
|
||||
currentEnv = process.env.NODE_ENV;
|
||||
currentEnv = process.env.NODE_ENV,
|
||||
ONE_HOUR_S = 60 * 60;
|
||||
|
||||
describe("Error handling", function () {
|
||||
|
||||
// Just getting rid of jslint unused error
|
||||
should.exist(errors);
|
||||
|
||||
it("throws error objects", function () {
|
||||
var toThrow = new Error("test1"),
|
||||
runThrowError = function () {
|
||||
errors.throwError(toThrow);
|
||||
};
|
||||
describe('Throwing', function () {
|
||||
it("throws error objects", function () {
|
||||
var toThrow = new Error("test1"),
|
||||
runThrowError = function () {
|
||||
errors.throwError(toThrow);
|
||||
};
|
||||
|
||||
runThrowError.should['throw']("test1");
|
||||
});
|
||||
runThrowError.should['throw']("test1");
|
||||
});
|
||||
|
||||
it("throws error strings", function () {
|
||||
var toThrow = "test2",
|
||||
runThrowError = function () {
|
||||
errors.throwError(toThrow);
|
||||
};
|
||||
it("throws error strings", function () {
|
||||
var toThrow = "test2",
|
||||
runThrowError = function () {
|
||||
errors.throwError(toThrow);
|
||||
};
|
||||
|
||||
runThrowError.should['throw']("test2");
|
||||
});
|
||||
runThrowError.should['throw']("test2");
|
||||
});
|
||||
|
||||
it("throws error even if nothing passed", function () {
|
||||
var runThrowError = function () {
|
||||
it("throws error even if nothing passed", function () {
|
||||
var runThrowError = function () {
|
||||
errors.throwError();
|
||||
};
|
||||
|
||||
runThrowError.should['throw']("An error occurred");
|
||||
});
|
||||
|
||||
it("logs errors", function () {
|
||||
var err = new Error("test1"),
|
||||
logStub = sinon.stub(console, "error");
|
||||
|
||||
// give environment a value that will console log
|
||||
process.env.NODE_ENV = "development";
|
||||
errors.logError(err);
|
||||
|
||||
// Calls log with message on Error objects
|
||||
logStub.calledWith("\nERROR:".red, err.message.red).should.equal(true);
|
||||
|
||||
logStub.reset();
|
||||
|
||||
err = "test2";
|
||||
|
||||
errors.logError(err);
|
||||
|
||||
// Calls log with string on strings
|
||||
logStub.calledWith("\nERROR:".red, err.red).should.equal(true);
|
||||
|
||||
logStub.restore();
|
||||
process.env.NODE_ENV = currentEnv;
|
||||
|
||||
});
|
||||
|
||||
it("logs promise errors and redirects", function (done) {
|
||||
var def = when.defer(),
|
||||
prom = def.promise,
|
||||
req = null,
|
||||
res = {
|
||||
redirect: function () {
|
||||
return;
|
||||
}
|
||||
},
|
||||
logStub = sinon.stub(console, "error"),
|
||||
redirectStub = sinon.stub(res, "redirect");
|
||||
|
||||
// give environment a value that will console log
|
||||
process.env.NODE_ENV = "development";
|
||||
prom.then(function () {
|
||||
throw new Error("Ran success handler");
|
||||
}, errors.logErrorWithRedirect("test1", null, null, "/testurl", req, res));
|
||||
|
||||
prom.otherwise(function () {
|
||||
logStub.calledWith("\nERROR:".red, "test1".red).should.equal(true);
|
||||
logStub.restore();
|
||||
|
||||
redirectStub.calledWith('/testurl').should.equal(true);
|
||||
redirectStub.restore();
|
||||
|
||||
done();
|
||||
runThrowError.should['throw']("An error occurred");
|
||||
});
|
||||
prom.ensure(function () {
|
||||
// gives the environment the correct value back
|
||||
});
|
||||
|
||||
describe('Logging', function () {
|
||||
var logStub;
|
||||
|
||||
beforeEach(function () {
|
||||
logStub = sinon.stub(console, "error");
|
||||
// give environment a value that will console log
|
||||
process.env.NODE_ENV = "development";
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
logStub.restore();
|
||||
// reset the environment
|
||||
process.env.NODE_ENV = currentEnv;
|
||||
});
|
||||
def.reject();
|
||||
|
||||
it("logs errors from error objects", function () {
|
||||
var err = new Error("test1");
|
||||
|
||||
errors.logError(err);
|
||||
|
||||
// Calls log with message on Error objects
|
||||
logStub.calledThrice.should.be.true;
|
||||
logStub.firstCall.calledWith("\nERROR:".red, err.message.red).should.be.true;
|
||||
logStub.secondCall.calledWith('').should.be.true;
|
||||
logStub.thirdCall.calledWith(err.stack, '\n').should.be.true;
|
||||
|
||||
});
|
||||
|
||||
it("logs errors from strings", function () {
|
||||
var err = "test2";
|
||||
|
||||
errors.logError(err);
|
||||
|
||||
// Calls log with string on strings
|
||||
logStub.calledTwice.should.be.true;
|
||||
logStub.firstCall.calledWith("\nERROR:".red, err.red).should.be.true;
|
||||
logStub.secondCall.calledWith('').should.be.true;
|
||||
});
|
||||
|
||||
it("logs errors from an error object and two string arguments", function () {
|
||||
var err = new Error("test1"),
|
||||
message = "Testing";
|
||||
|
||||
errors.logError(err, message, message);
|
||||
|
||||
// Calls log with message on Error objects
|
||||
|
||||
logStub.callCount.should.equal(5);
|
||||
logStub.calledWith("\nERROR:".red, err.message.red).should.be.true;
|
||||
logStub.firstCall.calledWith("\nERROR:".red, err.message.red).should.be.true;
|
||||
logStub.secondCall.calledWith(message.white).should.be.true;
|
||||
logStub.thirdCall.calledWith(message.green).should.be.true;
|
||||
logStub.getCall(3).calledWith('').should.be.true; //nth call uses zero-based numbering
|
||||
logStub.lastCall.calledWith(err.stack, '\n').should.be.true;
|
||||
});
|
||||
|
||||
it("logs errors from three string arguments", function () {
|
||||
var message = "Testing";
|
||||
|
||||
errors.logError(message, message, message);
|
||||
|
||||
// Calls log with message on Error objects
|
||||
|
||||
logStub.callCount.should.equal(4);
|
||||
logStub.firstCall.calledWith("\nERROR:".red, message.red).should.be.true;
|
||||
logStub.secondCall.calledWith(message.white).should.be.true;
|
||||
logStub.thirdCall.calledWith(message.green).should.be.true;
|
||||
logStub.lastCall.calledWith('').should.be.true;
|
||||
});
|
||||
|
||||
it("logs promise errors and redirects", function (done) {
|
||||
var def = when.defer(),
|
||||
prom = def.promise,
|
||||
req = null,
|
||||
res = {
|
||||
redirect: function () {
|
||||
return;
|
||||
}
|
||||
},
|
||||
redirectStub = sinon.stub(res, "redirect");
|
||||
|
||||
// give environment a value that will console log
|
||||
prom.then(function () {
|
||||
throw new Error("Ran success handler");
|
||||
}, errors.logErrorWithRedirect("test1", null, null, "/testurl", req, res));
|
||||
|
||||
prom.otherwise(function () {
|
||||
logStub.calledWith("\nERROR:".red, "test1".red).should.equal(true);
|
||||
logStub.restore();
|
||||
|
||||
redirectStub.calledWith('/testurl').should.equal(true);
|
||||
redirectStub.restore();
|
||||
|
||||
done();
|
||||
});
|
||||
def.reject();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Rendering', function () {
|
||||
var sandbox;
|
||||
|
||||
before(function () {
|
||||
errors.updateActiveTheme('casper', false);
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
|
||||
it('Renders end-of-middleware 404 errors correctly', function (done) {
|
||||
var req = {method: 'GET'},
|
||||
res = express.response;
|
||||
|
||||
sandbox.stub(express.response, 'render', function (view, options, fn) {
|
||||
view.should.match(/user-error\.hbs/);
|
||||
|
||||
// Test that the message is correct
|
||||
options.message.should.equal('Page Not Found');
|
||||
options.code.should.equal(404);
|
||||
this.statusCode.should.equal(404);
|
||||
|
||||
// Test that the headers are correct
|
||||
this._headers['cache-control'].should.equal('public, max-age=' + ONE_HOUR_S);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
sandbox.stub(express.response, 'status', function (status) {
|
||||
res.statusCode = status;
|
||||
return res;
|
||||
});
|
||||
|
||||
errors.error404(req, res, done);
|
||||
});
|
||||
|
||||
it('Renders thrown 404 errors correctly', function (done) {
|
||||
var err = new Error('A thing was not found'),
|
||||
req = {method: 'GET'},
|
||||
res = express.response;
|
||||
|
||||
sandbox.stub(express.response, 'render', function (view, options, fn) {
|
||||
view.should.match(/user-error\.hbs/);
|
||||
|
||||
// Test that the message is correct
|
||||
options.message.should.equal('Page Not Found');
|
||||
options.code.should.equal(404);
|
||||
this.statusCode.should.equal(404);
|
||||
|
||||
// Test that the headers are correct
|
||||
this._headers['cache-control'].should.equal('public, max-age=' + ONE_HOUR_S);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
sandbox.stub(express.response, 'status', function (status) {
|
||||
res.statusCode = status;
|
||||
return res;
|
||||
});
|
||||
|
||||
|
||||
err.status = 404;
|
||||
errors.error500(err, req, res, null);
|
||||
});
|
||||
|
||||
it('Renders thrown errors correctly', function (done) {
|
||||
var err = new Error('I am a big bad error'),
|
||||
req = {method: 'GET'},
|
||||
res = express.response;
|
||||
|
||||
sandbox.stub(express.response, 'render', function (view, options, fn) {
|
||||
view.should.match(/user-error\.hbs/);
|
||||
|
||||
// Test that the message is correct
|
||||
options.message.should.equal('I am a big bad error');
|
||||
options.code.should.equal(500);
|
||||
this.statusCode.should.equal(500);
|
||||
|
||||
// Test that the headers are correct
|
||||
this._headers['cache-control'].should.equal('no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
sandbox.stub(express.response, 'status', function (status) {
|
||||
res.statusCode = status;
|
||||
return res;
|
||||
});
|
||||
|
||||
errors.error500(err, req, res, null);
|
||||
});
|
||||
|
||||
it('Renders 500 errors correctly', function (done) {
|
||||
var err = new Error('I am a big bad error'),
|
||||
req = {method: 'GET'},
|
||||
res = express.response;
|
||||
|
||||
sandbox.stub(express.response, 'render', function (view, options, fn) {
|
||||
view.should.match(/user-error\.hbs/);
|
||||
|
||||
// Test that the message is correct
|
||||
options.message.should.equal('I am a big bad error');
|
||||
options.code.should.equal(500);
|
||||
this.statusCode.should.equal(500);
|
||||
|
||||
// Test that the headers are correct
|
||||
this._headers['cache-control'].should.equal('no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
sandbox.stub(express.response, 'status', function (status) {
|
||||
res.statusCode = status;
|
||||
return res;
|
||||
});
|
||||
|
||||
err.code = 500;
|
||||
errors.error500(err, req, res, null);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user