0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Merge pull request #3866 from hswolff/config-updates

Move config module to be instance based and merge bootstrap into config.
This commit is contained in:
Hannah Wolfe 2014-08-29 21:35:56 +01:00
commit 1ed286d09e
14 changed files with 629 additions and 596 deletions

View file

@ -637,9 +637,9 @@ var path = require('path'),
// Ghost requires a `config.js` file to specify the database settings etc. Ghost comes with an example file:
// `config.example.js` which is copied and renamed to `config.js` by the bootstrap process
grunt.registerTask('ensureConfig', function () {
var bootstrap = require('./core/bootstrap'),
var config = require('./core/server/config'),
done = this.async();
bootstrap().then(function () {
config.load().then(function () {
done();
}).catch(function (err) {
grunt.fail.fatal(err.stack);

140
core/bootstrap.js vendored
View file

@ -1,140 +0,0 @@
// This file manages the root level config.js.
// It will create config.js from config.exampe.js
// if it doesn't exist and then always attempt to load
// config.js into memory, error and quitting if config.js
// has an improper format.
var fs = require('fs'),
url = require('url'),
Promise = require('bluebird'),
validator = require('validator'),
errors = require('./server/errors'),
config = require('./server/config'),
appRoot = config.paths.appRoot,
configExample = config.paths.configExample,
configFile;
function readConfigFile(envVal) {
return require(configFile)[envVal];
}
function writeConfigFile() {
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
return new Promise(function (resolve, reject) {
fs.exists(configExample, function checkTemplate(templateExists) {
var read,
write,
error;
if (!templateExists) {
error = new Error('Could not locate a configuration file.');
error.context = appRoot;
error.help = 'Please check your deployment for config.js or config.example.js.';
return reject(error);
}
// Copy config.example.js => config.js
read = fs.createReadStream(configExample);
read.on('error', function (err) {
errors.logError(new Error('Could not open config.example.js for read.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
reject(err);
});
write = fs.createWriteStream(configFile);
write.on('error', function (err) {
errors.logError(new Error('Could not open config.js for write.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
reject(err);
});
write.on('finish', resolve);
read.pipe(write);
});
});
}
function validateConfigEnvironment() {
var envVal = process.env.NODE_ENV || undefined,
hasHostAndPort,
hasSocket,
config,
parsedUrl;
try {
config = readConfigFile(envVal);
}
catch (e) {
return Promise.reject(e);
}
// Check if we don't even have a config
if (!config) {
errors.logError(new Error('Cannot find the configuration for the current NODE_ENV'), 'NODE_ENV=' + envVal,
'Ensure your config.js has a section for the current NODE_ENV value and is formatted properly.');
return Promise.reject(new Error('Unable to load config for NODE_ENV=' + envVal));
}
// Check that our url is valid
if (!validator.isURL(config.url, { protocols: ['http', 'https'], require_protocol: true })) {
errors.logError(new Error('Your site url in config.js is invalid.'), config.url, 'Please make sure this is a valid url before restarting');
return Promise.reject(new Error('invalid site url'));
}
parsedUrl = url.parse(config.url || 'invalid', false, true);
if (/\/ghost(\/|$)/.test(parsedUrl.pathname)) {
errors.logError(new Error('Your site url in config.js cannot contain a subdirectory called ghost.'), config.url, 'Please rename the subdirectory before restarting');
return Promise.reject(new Error('ghost subdirectory not allowed'));
}
// Check that we have database values
if (!config.database || !config.database.client) {
errors.logError(new Error('Your database configuration in config.js is invalid.'), JSON.stringify(config.database), 'Please make sure this is a valid Bookshelf database configuration');
return Promise.reject(new Error('invalid database configuration'));
}
hasHostAndPort = config.server && !!config.server.host && !!config.server.port;
hasSocket = config.server && !!config.server.socket;
// Check for valid server host and port values
if (!config.server || !(hasHostAndPort || hasSocket)) {
errors.logError(new Error('Your server values (socket, or host and port) in config.js are invalid.'), JSON.stringify(config.server), 'Please provide them before restarting.');
return Promise.reject(new Error('invalid server configuration'));
}
return Promise.resolve(config);
}
function loadConfig(configFilePath) {
configFile = process.env.GHOST_CONFIG || configFilePath || config.paths.config;
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
return new Promise(function (resolve, reject) {
fs.exists(configFile, function (exists) {
var pendingConfig;
if (!exists) {
pendingConfig = writeConfigFile();
}
Promise.resolve(pendingConfig)
.then(validateConfigEnvironment)
.then(function (rawConfig) {
resolve(config.init(rawConfig));
}).catch(reject);
});
});
}
module.exports = loadConfig;

View file

@ -2,17 +2,14 @@
// Orchestrates the loading of Ghost
// When run from command line.
var bootstrap = require('./bootstrap'),
server = require('./server');
var server = require('./server');
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
function makeGhost(options) {
options = options || {};
return bootstrap(options.config).then(function () {
return server(options.app);
});
return server(options);
}
module.exports = makeGhost;

View file

@ -5,44 +5,90 @@
var path = require('path'),
Promise = require('bluebird'),
fs = require('fs'),
url = require('url'),
_ = require('lodash'),
knex = require('knex'),
validator = require('validator'),
requireTree = require('../require-tree').readAll,
errors = require('../errors'),
theme = require('./theme'),
configUrl = require('./url'),
ghostConfig = {},
appRoot = path.resolve(__dirname, '../../../'),
corePath = path.resolve(appRoot, 'core/'),
testingEnvs = ['testing', 'testing-mysql', 'testing-pg'],
defaultConfig = {},
knexInstance;
// Are we using sockets? Custom socket or the default?
function getSocket() {
if (ghostConfig.server.hasOwnProperty('socket')) {
return _.isString(ghostConfig.server.socket) ? ghostConfig.server.socket : path.join(ghostConfig.paths.contentPath, process.env.NODE_ENV + '.socket');
function ConfigManager(config) {
/**
* Our internal true representation of our current config object.
* @private
* @type {Object}
*/
this._config = {};
// Allow other modules to be externally accessible.
this.theme = theme;
this.urlFor = configUrl.urlFor;
this.urlForPost = configUrl.urlForPost;
// If we're given an initial config object then we can set it.
if (config && _.isObject(config)) {
this.set(config);
}
return false;
}
function updateConfig(config) {
// Are we using sockets? Custom socket or the default?
ConfigManager.prototype.getSocket = function () {
if (this._config.server.hasOwnProperty('socket')) {
return _.isString(this._config.server.socket) ?
this._config.server.socket :
path.join(this._config.paths.contentPath, process.env.NODE_ENV + '.socket');
}
return false;
};
ConfigManager.prototype.init = function (rawConfig) {
var self = this;
// Cache the config.js object's environment
// object so we can later refer to it.
// Note: this is not the entirety of config.js,
// just the object appropriate for this NODE_ENV
self.set(rawConfig);
return Promise.all([requireTree(self._config.paths.themePath), requireTree(self._config.paths.appPath)]).then(function (paths) {
self._config.paths.availableThemes = paths[0];
self._config.paths.availableApps = paths[1];
return self._config;
});
};
/**
* Allows you to set the config object.
* @param {Object} config Only accepts an object at the moment.
*/
ConfigManager.prototype.set = function (config) {
var localPath = '',
contentPath,
subdir;
// Merge passed in config object onto
// the cached ghostConfig object
_.merge(ghostConfig, config);
// Merge passed in config object onto our existing config object.
// We're using merge here as it doesn't assign `undefined` properties
// onto our cached config object. This allows us to only update our
// local copy with properties that have been explicitly set.
_.merge(this._config, config);
// Protect against accessing a non-existant object.
// This ensures there's always at least a paths object
// because it's referenced in multiple places.
ghostConfig.paths = ghostConfig.paths || {};
this._config.paths = this._config.paths || {};
// Parse local path location
if (ghostConfig.url) {
localPath = url.parse(ghostConfig.url).path;
if (this._config.url) {
localPath = url.parse(this._config.url).path;
// Remove trailing slash
if (localPath !== '/') {
localPath = localPath.replace(/\/$/, '');
@ -53,20 +99,20 @@ function updateConfig(config) {
// Allow contentPath to be over-written by passed in config object
// Otherwise default to default content path location
contentPath = ghostConfig.paths.contentPath || path.resolve(appRoot, 'content');
contentPath = this._config.paths.contentPath || path.resolve(appRoot, 'content');
if (!knexInstance && ghostConfig.database && ghostConfig.database.client) {
knexInstance = knex(ghostConfig.database);
if (!knexInstance && this._config.database && this._config.database.client) {
knexInstance = knex(this._config.database);
}
_.merge(ghostConfig, {
_.merge(this._config, {
database: {
knex: knexInstance
},
paths: {
'appRoot': appRoot,
'subdir': subdir,
'config': ghostConfig.paths.config || path.join(appRoot, 'config.js'),
'config': this._config.paths.config || path.join(appRoot, 'config.js'),
'configExample': path.join(appRoot, 'config.example.js'),
'corePath': corePath,
@ -82,8 +128,8 @@ function updateConfig(config) {
'lang': path.join(corePath, '/shared/lang/'),
'debugPath': subdir + '/ghost/debug/',
'availableThemes': ghostConfig.paths.availableThemes || {},
'availableApps': ghostConfig.paths.availableApps || {},
'availableThemes': this._config.paths.availableThemes || {},
'availableApps': this._config.paths.availableApps || {},
'builtScriptPath': path.join(corePath, 'built/scripts/')
}
});
@ -91,33 +137,161 @@ function updateConfig(config) {
// Also pass config object to
// configUrl object to maintain
// clean depedency tree
configUrl.setConfig(ghostConfig);
}
configUrl.setConfig(this._config);
function initConfig(rawConfig) {
// Cache the config.js object's environment
// object so we can later refer to it.
// Note: this is not the entirety of config.js,
// just the object appropriate for this NODE_ENV
updateConfig(rawConfig);
// For now we're going to copy the current state of this._config
// so it's directly accessible on the instance.
// @TODO: perhaps not do this? Put access of the config object behind
// a function?
_.extend(this, this._config);
};
return Promise.all([requireTree(ghostConfig.paths.themePath), requireTree(ghostConfig.paths.appPath)]).then(function (paths) {
ghostConfig.paths.availableThemes = paths[0];
ghostConfig.paths.availableApps = paths[1];
return ghostConfig;
/**
* Allows you to read the config object.
* @return {Object} The config object.
*/
ConfigManager.prototype.get = function () {
return this._config;
};
ConfigManager.prototype.load = function (configFilePath) {
var self = this;
self._config.paths.config = process.env.GHOST_CONFIG || configFilePath || self._config.paths.config;
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
return new Promise(function (resolve, reject) {
fs.exists(self._config.paths.config, function (exists) {
var pendingConfig;
if (!exists) {
pendingConfig = self.writeFile();
}
Promise.resolve(pendingConfig).then(function () {
return self.validate();
}).then(function (rawConfig) {
resolve(self.init(rawConfig));
}).catch(reject);
});
});
}
};
/* Check for config file and copy from config.example.js
if one doesn't exist. After that, start the server. */
ConfigManager.prototype.writeFile = function () {
var configPath = this._config.paths.config,
configExamplePath = this._config.paths.configExample;
return new Promise(function (resolve, reject) {
fs.exists(configExamplePath, function checkTemplate(templateExists) {
var read,
write,
error;
if (!templateExists) {
error = new Error('Could not locate a configuration file.');
error.context = appRoot;
error.help = 'Please check your deployment for config.js or config.example.js.';
return reject(error);
}
// Copy config.example.js => config.js
read = fs.createReadStream(configExamplePath);
read.on('error', function (err) {
errors.logError(new Error('Could not open config.example.js for read.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
reject(err);
});
write = fs.createWriteStream(configPath);
write.on('error', function (err) {
errors.logError(new Error('Could not open config.js for write.'), appRoot, 'Please check your deployment for config.js or config.example.js.');
reject(err);
});
write.on('finish', resolve);
read.pipe(write);
});
});
};
/**
* Read config.js file from file system using node's require
* @param {String} envVal Which environment we're in.
* @return {Object} The config object.
*/
ConfigManager.prototype.readFile = function (envVal) {
return require(this._config.paths.config)[envVal];
};
/**
* Validates the config object has everything we want and in the form we want.
* @return {Promise.<Object>} Returns a promise that resolves to the config object.
*/
ConfigManager.prototype.validate = function () {
var envVal = process.env.NODE_ENV || undefined,
hasHostAndPort,
hasSocket,
config,
parsedUrl;
try {
config = this.readFile(envVal);
}
catch (e) {
return Promise.reject(e);
}
// Check if we don't even have a config
if (!config) {
errors.logError(new Error('Cannot find the configuration for the current NODE_ENV'), 'NODE_ENV=' + envVal,
'Ensure your config.js has a section for the current NODE_ENV value and is formatted properly.');
return Promise.reject(new Error('Unable to load config for NODE_ENV=' + envVal));
}
// Check that our url is valid
if (!validator.isURL(config.url, { protocols: ['http', 'https'], require_protocol: true })) {
errors.logError(new Error('Your site url in config.js is invalid.'), config.url, 'Please make sure this is a valid url before restarting');
return Promise.reject(new Error('invalid site url'));
}
parsedUrl = url.parse(config.url || 'invalid', false, true);
if (/\/ghost(\/|$)/.test(parsedUrl.pathname)) {
errors.logError(new Error('Your site url in config.js cannot contain a subdirectory called ghost.'), config.url, 'Please rename the subdirectory before restarting');
return Promise.reject(new Error('ghost subdirectory not allowed'));
}
// Check that we have database values
if (!config.database || !config.database.client) {
errors.logError(new Error('Your database configuration in config.js is invalid.'), JSON.stringify(config.database), 'Please make sure this is a valid Bookshelf database configuration');
return Promise.reject(new Error('invalid database configuration'));
}
hasHostAndPort = config.server && !!config.server.host && !!config.server.port;
hasSocket = config.server && !!config.server.socket;
// Check for valid server host and port values
if (!config.server || !(hasHostAndPort || hasSocket)) {
errors.logError(new Error('Your server values (socket, or host and port) in config.js are invalid.'), JSON.stringify(config.server), 'Please provide them before restarting.');
return Promise.reject(new Error('invalid server configuration'));
}
return Promise.resolve(config);
};
if (testingEnvs.indexOf(process.env.NODE_ENV) > -1) {
defaultConfig = require('../../../config.example')[process.env.NODE_ENV];
}
// Init config
updateConfig(defaultConfig);
module.exports = ghostConfig;
module.exports.init = initConfig;
module.exports.theme = theme;
module.exports.getSocket = getSocket;
module.exports.urlFor = configUrl.urlFor;
module.exports.urlForPost = configUrl.urlForPost;
module.exports = new ConfigManager(defaultConfig);

View file

@ -1,7 +1,6 @@
/*jslint regexp: true */
var _ = require('lodash'),
colors = require('colors'),
config = require('../config'),
path = require('path'),
Promise = require('bluebird'),
hbs = require('express-hbs'),
@ -15,21 +14,31 @@ var _ = require('lodash'),
UnsupportedMediaTypeError = require('./unsupportedmediaerror'),
EmailError = require('./emailerror'),
DataImportError = require('./dataimporterror'),
config,
errors,
// Paths for views
defaultErrorTemplatePath = path.resolve(config.paths.adminViews, 'user-error.hbs'),
userErrorTemplateExists = false;
// This is not useful but required for jshint
colors.setTheme({silly: 'rainbow'});
// Shim right now to deal with circular dependencies.
// @TODO: remove circular dependency
function getConfigModule() {
if (!config) {
config = require('../config');
}
return config;
}
/**
* Basic error handling helpers
*/
errors = {
updateActiveTheme: function (activeTheme) {
userErrorTemplateExists = config.paths.availableThemes[activeTheme].hasOwnProperty('error.hbs');
userErrorTemplateExists = getConfigModule().paths.availableThemes[activeTheme].hasOwnProperty('error.hbs');
},
throwError: function (err) {
@ -185,7 +194,8 @@ errors = {
renderErrorPage: function (code, err, req, res, next) {
/*jshint unused:false*/
var self = this;
var self = this,
defaultErrorTemplatePath = path.resolve(getConfigModule().paths.adminViews, 'user-error.hbs');
function parseStack(stack) {
if (!_.isString(stack)) {

View file

@ -129,23 +129,22 @@ function initNotifications() {
// Sets up the express server instance.
// Instantiates the ghost singleton, helpers, routes, middleware, and apps.
// Finally it returns an instance of GhostServer
function init(server) {
// create a hash for cache busting assets
var assetHash = (crypto.createHash('md5').update(packageInfo.version + Date.now()).digest('hex')).substring(0, 10);
// If no express instance is passed in
// then create our own
if (!server) {
server = express();
}
function init(options) {
// Get reference to an express app instance.
var server = options.app ? options.app : express(),
// create a hash for cache busting assets
assetHash = (crypto.createHash('md5').update(packageInfo.version + Date.now()).digest('hex')).substring(0, 10);
// ### Initialisation
// The server and its dependencies require a populated config
// It returns a promise that is resolved when the application
// has finished starting up.
// Make sure javascript files have been built via grunt concat
return builtFilesExist().then(function () {
// Load our config.js file from the local file system.
return config.load(options.config).then(function () {
// Make sure javascript files have been built via grunt concat
return builtFilesExist();
}).then(function () {
// Initialise the models
return models.init();
}).then(function () {

View file

@ -11,7 +11,6 @@ var testUtils = require('../utils/index'),
// Stuff we are testing
config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig'),
defaultConfig = rewire('../../../config.example')[process.env.NODE_ENV],
migration = rewire('../../server/data/migration'),
versioning = require('../../server/data/versioning'),
@ -43,7 +42,7 @@ describe('Import', function () {
var newConfig = _.extend(config, defaultConfig);
migration.__get__('config', newConfig);
configUpdate(newConfig);
config.set(newConfig);
knex = config.database.knex;
});

View file

@ -1,323 +0,0 @@
/*globals describe, it, beforeEach, afterEach */
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
path = require('path'),
fs = require('fs'),
_ = require('lodash'),
rewire = require('rewire'),
// Thing we are testing
defaultConfig = require('../../../config.example')[process.env.NODE_ENV],
bootstrap = rewire('../../bootstrap'),
config = rewire('../../server/config');
describe('Bootstrap', function () {
var sandbox,
overrideConfig = function (newConfig) {
bootstrap.__set__('readConfigFile', sandbox.stub().returns(
_.extend({}, defaultConfig, newConfig)
));
},
expectedError = new Error('expected bootstrap() to throw error but none thrown');
beforeEach(function () {
sandbox = sinon.sandbox.create();
});
afterEach(function () {
bootstrap = rewire('../../bootstrap');
sandbox.restore();
});
it('loads the config file if one exists', function (done) {
// the test infrastructure is setup so that there is always config present,
// but we want to overwrite the test to actually load config.example.js, so that any local changes
// don't break the tests
bootstrap.__set__('configFile', path.join(config.paths.appRoot, 'config.example.js'));
bootstrap().then(function (config) {
config.url.should.equal(defaultConfig.url);
config.database.client.should.equal(defaultConfig.database.client);
config.database.connection.should.eql(defaultConfig.database.connection);
config.server.host.should.equal(defaultConfig.server.host);
config.server.port.should.equal(defaultConfig.server.port);
done();
}).catch(done);
});
it('uses the passed in config file location', function (done) {
bootstrap(path.join(config.paths.appRoot, 'config.example.js')).then(function (config) {
config.url.should.equal(defaultConfig.url);
config.database.client.should.equal(defaultConfig.database.client);
config.database.connection.should.eql(defaultConfig.database.connection);
config.server.host.should.equal(defaultConfig.server.host);
config.server.port.should.equal(defaultConfig.server.port);
done();
}).catch(done);
});
it('creates the config file if one does not exist', function (done) {
// trick bootstrap into thinking that the config file doesn't exist yet
var existsStub = sandbox.stub(fs, 'exists', function (file, cb) { return cb(false); }),
// create a method which will return a pre-resolved promise
resolvedPromise = sandbox.stub().returns(Promise.resolve());
// ensure that the file creation is a stub, the tests shouldn't really create a file
bootstrap.__set__('writeConfigFile', resolvedPromise);
bootstrap.__set__('validateConfigEnvironment', resolvedPromise);
bootstrap().then(function () {
existsStub.calledOnce.should.be.true;
resolvedPromise.calledTwice.should.be.true;
done();
}).catch(done);
});
it('accepts urls with a valid scheme', function (done) {
// replace the config file with invalid data
overrideConfig({url: 'http://testurl.com'});
bootstrap().then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com');
// Next test
overrideConfig({url: 'https://testurl.com'});
return bootstrap();
}).then(function (localConfig) {
localConfig.url.should.equal('https://testurl.com');
// Next test
overrideConfig({url: 'http://testurl.com/blog/'});
return bootstrap();
}).then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com/blog/');
// Next test
overrideConfig({url: 'http://testurl.com/ghostly/'});
return bootstrap();
}).then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com/ghostly/');
done();
}).catch(done);
});
it('rejects a fqdn without a scheme', function (done) {
overrideConfig({ url: 'example.com' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a hostname without a scheme', function (done) {
overrideConfig({ url: 'example' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a hostname with a scheme', function (done) {
overrideConfig({ url: 'https://example' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a url with an unsupported scheme', function (done) {
overrideConfig({ url: 'ftp://example.com' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a url with a protocol relative scheme', function (done) {
overrideConfig({ url: '//example.com' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost as a url path', function (done) {
overrideConfig({ url: 'http://example.com/ghost/' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost to be a component in a url path', function (done) {
overrideConfig({ url: 'http://example.com/blog/ghost/' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost to be a component in a url path', function (done) {
overrideConfig({ url: 'http://example.com/ghost/blog/' });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit database config to be falsy', function (done) {
// replace the config file with invalid data
overrideConfig({ database: false });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit database config to be empty', function (done) {
// replace the config file with invalid data
overrideConfig({ database: {} });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('requires server to be present', function (done) {
overrideConfig({ server: false });
bootstrap().then(function (localConfig) {
/*jshint unused:false*/
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('allows server to use a socket', function (done) {
overrideConfig({ server: { socket: 'test' } });
bootstrap().then(function (localConfig) {
should.exist(localConfig);
localConfig.server.socket.should.equal('test');
done();
}).catch(done);
});
it('allows server to have a host and a port', function (done) {
overrideConfig({ server: { host: '127.0.0.1', port: '2368' } });
bootstrap().then(function (localConfig) {
should.exist(localConfig);
localConfig.server.host.should.equal('127.0.0.1');
localConfig.server.port.should.equal('2368');
done();
}).catch(done);
});
it('rejects server if there is a host but no port', function (done) {
overrideConfig({ server: { host: '127.0.0.1' } });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects server if there is a port but no host', function (done) {
overrideConfig({ server: { port: '2368' } });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects server if configuration is empty', function (done) {
overrideConfig({ server: {} });
bootstrap().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
});

View file

@ -4,6 +4,7 @@ var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
path = require('path'),
fs = require('fs'),
_ = require('lodash'),
rewire = require('rewire'),
@ -12,8 +13,7 @@ var should = require('should'),
// Thing we are testing
defaultConfig = require('../../../config.example')[process.env.NODE_ENV],
theme = rewire('../../server/config/theme'),
config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig');
config = rewire('../../server/config');
// To stop jshint complaining
should.equal(true, true);
@ -76,7 +76,7 @@ describe('Config', function () {
// Make a copy of the default config file
// so we can restore it after every test.
// Using _.merge to recursively apply every property.
configUpdate(_.merge({}, config));
config.set(_.merge({}, config));
});
it('should have exactly the right keys', function () {
@ -114,24 +114,24 @@ describe('Config', function () {
});
it('should not return a slash for subdir', function () {
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.paths.should.have.property('subdir', '');
configUpdate({url: 'http://my-ghost-blog.com/'});
config.set({url: 'http://my-ghost-blog.com/'});
config.paths.should.have.property('subdir', '');
});
it('should handle subdirectories properly', function () {
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.paths.should.have.property('subdir', '/blog');
configUpdate({url: 'http://my-ghost-blog.com/blog/'});
config.set({url: 'http://my-ghost-blog.com/blog/'});
config.paths.should.have.property('subdir', '/blog');
configUpdate({url: 'http://my-ghost-blog.com/my/blog'});
config.set({url: 'http://my-ghost-blog.com/my/blog'});
config.paths.should.have.property('subdir', '/my/blog');
configUpdate({url: 'http://my-ghost-blog.com/my/blog/'});
config.set({url: 'http://my-ghost-blog.com/my/blog/'});
config.paths.should.have.property('subdir', '/my/blog');
});
@ -139,7 +139,7 @@ describe('Config', function () {
var contentPath = path.join(config.paths.appRoot, 'otherContent', '/'),
configFile = 'configFileDanceParty.js';
configUpdate({
config.set({
config: configFile,
paths: {
contentPath: contentPath
@ -157,27 +157,27 @@ describe('Config', function () {
describe('urlFor', function () {
before(function () {
configUpdate(_.merge({}, defaultConfig));
config.set(_.merge({}, defaultConfig));
});
afterEach(function () {
configUpdate({url: defaultConfig.url});
config.set({url: defaultConfig.url});
});
it('should return the home url with no options', function () {
config.urlFor().should.equal('/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor().should.equal('/blog/');
});
it('should return home url when asked for', function () {
var testContext = 'home';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext).should.equal('/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext).should.equal('/blog/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/');
});
@ -185,11 +185,11 @@ describe('Config', function () {
it('should return rss url when asked for', function () {
var testContext = 'rss';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext).should.equal('/rss/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/rss/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext).should.equal('/blog/rss/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/rss/');
});
@ -197,11 +197,11 @@ describe('Config', function () {
it('should return url for a random path when asked for', function () {
var testContext = {relativeUrl: '/about/'};
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext).should.equal('/about/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/about/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext).should.equal('/blog/about/');
config.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/about/');
});
@ -210,11 +210,11 @@ describe('Config', function () {
var testContext = 'post',
testData = {post: testUtils.DataGenerator.Content.posts[2], permalinks: {value: '/:slug/'}};
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext, testData).should.equal('/short-and-sweet/');
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/short-and-sweet/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext, testData).should.equal('/blog/short-and-sweet/');
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog/short-and-sweet/');
});
@ -231,11 +231,11 @@ describe('Config', function () {
yyyy = today.getFullYear(),
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/short-and-sweet/';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext, testData).should.equal(postLink);
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com' + postLink);
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext, testData).should.equal('/blog' + postLink);
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog' + postLink);
});
@ -244,11 +244,11 @@ describe('Config', function () {
var testContext = 'tag',
testData = {tag: testUtils.DataGenerator.Content.tags[0]};
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
config.urlFor(testContext, testData).should.equal('/tag/kitchen-sink/');
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/tag/kitchen-sink/');
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config.set({url: 'http://my-ghost-blog.com/blog'});
config.urlFor(testContext, testData).should.equal('/blog/tag/kitchen-sink/');
config.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog/tag/kitchen-sink/');
});
@ -264,7 +264,7 @@ describe('Config', function () {
afterEach(function () {
sandbox.restore();
configUpdate({url: defaultConfig.url});
config.set({url: defaultConfig.url});
});
it('should output correct url for post', function (done) {
@ -276,7 +276,7 @@ describe('Config', function () {
testData = testUtils.DataGenerator.Content.posts[2],
postLink = '/short-and-sweet/';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
// next test
config.urlForPost(settings, testData).then(function (url) {
@ -287,7 +287,7 @@ describe('Config', function () {
}).then(function (url) {
url.should.equal('http://my-ghost-blog.com' + postLink);
return configUpdate({url: 'http://my-ghost-blog.com/blog'});
return config.set({url: 'http://my-ghost-blog.com/blog'});
}).then(function () {
// next test
@ -318,7 +318,7 @@ describe('Config', function () {
yyyy = today.getFullYear(),
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/short-and-sweet/';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
// next test
config.urlForPost(settings, testData).then(function (url) {
@ -329,7 +329,7 @@ describe('Config', function () {
}).then(function (url) {
url.should.equal('http://my-ghost-blog.com' + postLink);
return configUpdate({url: 'http://my-ghost-blog.com/blog'});
return config.set({url: 'http://my-ghost-blog.com/blog'});
}).then(function () {
// next test
@ -355,7 +355,7 @@ describe('Config', function () {
testData = testUtils.DataGenerator.Content.posts[5],
postLink = '/static-page-test/';
configUpdate({url: 'http://my-ghost-blog.com'});
config.set({url: 'http://my-ghost-blog.com'});
// next test
config.urlForPost(settings, testData).then(function (url) {
@ -366,7 +366,7 @@ describe('Config', function () {
}).then(function (url) {
url.should.equal('http://my-ghost-blog.com' + postLink);
return configUpdate({url: 'http://my-ghost-blog.com/blog'});
return config.set({url: 'http://my-ghost-blog.com/blog'});
}).then(function () {
// next test
@ -383,4 +383,327 @@ describe('Config', function () {
}).catch(done);
});
});
describe('File', function () {
var sandbox,
originalConfig,
readFileStub,
overrideConfig = function (newConfig) {
readFileStub.returns(
_.extend({}, defaultConfig, newConfig)
);
},
expectedError = new Error('expected bootstrap() to throw error but none thrown');
before(function () {
originalConfig = _.cloneDeep(rewire('../../server/config')._config);
});
beforeEach(function () {
sandbox = sinon.sandbox.create();
readFileStub = sandbox.stub(config, 'readFile');
});
afterEach(function () {
config = rewire('../../server/config');
sandbox.restore();
});
it('loads the config file if one exists', function (done) {
// We actually want the real method here.
readFileStub.restore();
// the test infrastructure is setup so that there is always config present,
// but we want to overwrite the test to actually load config.example.js, so that any local changes
// don't break the tests
config.set({
paths: {
appRoot: path.join(originalConfig.paths.appRoot, 'config.example.js')
}
});
config.load().then(function (config) {
config.url.should.equal(defaultConfig.url);
config.database.client.should.equal(defaultConfig.database.client);
config.database.connection.should.eql(defaultConfig.database.connection);
config.server.host.should.equal(defaultConfig.server.host);
config.server.port.should.equal(defaultConfig.server.port);
done();
}).catch(done);
});
it('uses the passed in config file location', function (done) {
// We actually want the real method here.
readFileStub.restore();
config.load(path.join(originalConfig.paths.appRoot, 'config.example.js')).then(function (config) {
config.url.should.equal(defaultConfig.url);
config.database.client.should.equal(defaultConfig.database.client);
config.database.connection.should.eql(defaultConfig.database.connection);
config.server.host.should.equal(defaultConfig.server.host);
config.server.port.should.equal(defaultConfig.server.port);
done();
}).catch(done);
});
it('creates the config file if one does not exist', function (done) {
// trick bootstrap into thinking that the config file doesn't exist yet
var existsStub = sandbox.stub(fs, 'exists', function (file, cb) { return cb(false); }),
// ensure that the file creation is a stub, the tests shouldn't really create a file
writeFileStub = sandbox.stub(config, 'writeFile').returns(Promise.resolve()),
validateStub = sandbox.stub(config, 'validate').returns(Promise.resolve());
config.load().then(function () {
existsStub.calledOnce.should.be.true;
writeFileStub.calledOnce.should.be.true;
validateStub.calledOnce.should.be.true;
done();
}).catch(done);
});
it('accepts urls with a valid scheme', function (done) {
// replace the config file with invalid data
overrideConfig({url: 'http://testurl.com'});
config.load().then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com');
// Next test
overrideConfig({url: 'https://testurl.com'});
return config.load();
}).then(function (localConfig) {
localConfig.url.should.equal('https://testurl.com');
// Next test
overrideConfig({url: 'http://testurl.com/blog/'});
return config.load();
}).then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com/blog/');
// Next test
overrideConfig({url: 'http://testurl.com/ghostly/'});
return config.load();
}).then(function (localConfig) {
localConfig.url.should.equal('http://testurl.com/ghostly/');
done();
}).catch(done);
});
it('rejects a fqdn without a scheme', function (done) {
overrideConfig({ url: 'example.com' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a hostname without a scheme', function (done) {
overrideConfig({ url: 'example' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a hostname with a scheme', function (done) {
overrideConfig({ url: 'https://example' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a url with an unsupported scheme', function (done) {
overrideConfig({ url: 'ftp://example.com' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects a url with a protocol relative scheme', function (done) {
overrideConfig({ url: '//example.com' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost as a url path', function (done) {
overrideConfig({ url: 'http://example.com/ghost/' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost to be a component in a url path', function (done) {
overrideConfig({ url: 'http://example.com/blog/ghost/' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit the word ghost to be a component in a url path', function (done) {
overrideConfig({ url: 'http://example.com/ghost/blog/' });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit database config to be falsy', function (done) {
// replace the config file with invalid data
overrideConfig({ database: false });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('does not permit database config to be empty', function (done) {
// replace the config file with invalid data
overrideConfig({ database: {} });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('requires server to be present', function (done) {
overrideConfig({ server: false });
config.load().then(function (localConfig) {
/*jshint unused:false*/
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('allows server to use a socket', function (done) {
overrideConfig({ server: { socket: 'test' } });
config.load().then(function (localConfig) {
should.exist(localConfig);
localConfig.server.socket.should.equal('test');
done();
}).catch(done);
});
it('allows server to have a host and a port', function (done) {
overrideConfig({ server: { host: '127.0.0.1', port: '2368' } });
config.load().then(function (localConfig) {
should.exist(localConfig);
localConfig.server.host.should.equal('127.0.0.1');
localConfig.server.port.should.equal('2368');
done();
}).catch(done);
});
it('rejects server if there is a host but no port', function (done) {
overrideConfig({ server: { host: '127.0.0.1' } });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects server if there is a port but no host', function (done) {
overrideConfig({ server: { port: '2368' } });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
it('rejects server if configuration is empty', function (done) {
overrideConfig({ server: {} });
config.load().then(function () {
done(expectedError);
}).catch(function (err) {
should.exist(err);
err.should.be.an.Error;
done();
}).catch(done);
});
});
});

View file

@ -5,10 +5,12 @@ var should = require('should'),
sinon = require('sinon'),
express = require('express'),
rewire = require('rewire'),
_ = require('lodash'),
// Stuff we are testing
colors = require('colors'),
config = rewire('../../server/config'),
errors = rewire('../../server/errors'),
// storing current environment
currentEnv = process.env.NODE_ENV;
@ -211,8 +213,8 @@ describe('Error handling', function () {
originalConfig;
before(function () {
originalConfig = errors.__get__('config');
errors.__set__('config', {
originalConfig = _.cloneDeep(config._config);
errors.__set__('getConfigModule', sinon.stub().returns(_.merge({}, originalConfig, {
'paths': {
'themePath': '/content/themes',
'availableThemes': {
@ -228,7 +230,7 @@ describe('Error handling', function () {
}
}
}
});
})));
errors.updateActiveTheme('casper');
});
@ -240,10 +242,6 @@ describe('Error handling', function () {
sandbox.restore();
});
after(function () {
errors.__set__('config', originalConfig);
});
it('Renders end-of-middleware 404 errors correctly', function (done) {
var req = {method: 'GET'},
res = express.response;

View file

@ -1021,10 +1021,9 @@ describe('Frontend Controller', function () {
describe('rss redirects', function () {
var res,
apiUsersStub,
configUpdate = config.__get__('updateConfig'),
overwriteConfig = function (newConfig) {
var existingConfig = frontend.__get__('config');
configUpdate(_.extend(existingConfig, newConfig));
config.set(_.extend(existingConfig, newConfig));
};
beforeEach(function () {

View file

@ -39,10 +39,9 @@ SENDMAIL = {
describe('Mail', function () {
var overrideConfig = function (newConfig) {
var config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig'),
existingConfig = mailer.__get__('config');
configUpdate(_.extend(existingConfig, newConfig));
config.set(_.extend(existingConfig, newConfig));
};
beforeEach(function () {

View file

@ -12,8 +12,7 @@ var should = require('should'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = rewire('../../server/helpers'),
config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig');
config = rewire('../../server/config');
describe('Core Helpers', function () {
@ -21,7 +20,7 @@ describe('Core Helpers', function () {
apiStub,
overrideConfig = function (newConfig) {
var existingConfig = helpers.__get__('config');
configUpdate(_.extend(existingConfig, newConfig));
config.set(_.extend(existingConfig, newConfig));
};
beforeEach(function (done) {
@ -496,7 +495,7 @@ describe('Core Helpers', function () {
var configUrl = config.url;
afterEach(function () {
configUpdate({url: configUrl});
config.set({url: configUrl});
});
it('has loaded ghost_head helper', function () {
@ -504,7 +503,7 @@ describe('Core Helpers', function () {
});
it('returns meta tag string', function (done) {
configUpdate({url: 'http://testurl.com/'});
config.set({url: 'http://testurl.com/'});
helpers.ghost_head.call({version: '0.3.0'}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
@ -516,7 +515,7 @@ describe('Core Helpers', function () {
});
it('returns meta tag string even if version is invalid', function (done) {
configUpdate({url: 'http://testurl.com/'});
config.set({url: 'http://testurl.com/'});
helpers.ghost_head.call({version: '0.9'}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n' +
@ -528,7 +527,7 @@ describe('Core Helpers', function () {
});
it('returns correct rss url with subdirectory', function (done) {
configUpdate({url: 'http://testurl.com/blog/'});
config.set({url: 'http://testurl.com/blog/'});
helpers.ghost_head.call({version: '0.3.0'}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
@ -540,7 +539,7 @@ describe('Core Helpers', function () {
});
it('returns canonical URL', function (done) {
configUpdate({url: 'http://testurl.com'});
config.set({url: 'http://testurl.com'});
helpers.ghost_head.call({version: '0.3.0', relativeUrl: '/about/'}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
@ -552,7 +551,7 @@ describe('Core Helpers', function () {
});
it('returns next & prev URL correctly for middle page', function (done) {
configUpdate({url: 'http://testurl.com'});
config.set({url: 'http://testurl.com'});
helpers.ghost_head.call({version: '0.3.0', relativeUrl: '/page/3/', pagination: {next: '4', prev: '2'}}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
@ -565,7 +564,7 @@ describe('Core Helpers', function () {
});
it('returns next & prev URL correctly for second page', function (done) {
configUpdate({url: 'http://testurl.com'});
config.set({url: 'http://testurl.com'});
helpers.ghost_head.call({version: '0.3.0', relativeUrl: '/page/2/', pagination: {next: '3', prev: '1'}}).then(function (rendered) {
should.exist(rendered);
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
@ -767,7 +766,7 @@ describe('Core Helpers', function () {
});
afterEach(function () {
configUpdate({url: configUrl});
config.set({url: configUrl});
});
it('has loaded url helper', function () {
@ -785,7 +784,7 @@ describe('Core Helpers', function () {
});
it('should output an absolute URL if the option is present', function (done) {
configUpdate({ url: 'http://testurl.com/' });
config.set({ url: 'http://testurl.com/' });
helpers.url.call(
{html: 'content', markdown: 'ff', title: 'title', slug: 'slug', created_at: new Date(0)},
@ -1711,7 +1710,7 @@ describe('Core Helpers', function () {
configUrl = config.url;
afterEach(function () {
configUpdate({url: configUrl});
config.set({url: configUrl});
});
@ -1722,7 +1721,7 @@ describe('Core Helpers', function () {
});
it('should output the path to admin with subdirectory', function () {
configUpdate({url: 'http://testurl.com/blog/'});
config.set({url: 'http://testurl.com/blog/'});
rendered = helpers.admin_url();
should.exist(rendered);
rendered.should.equal('/blog/ghost');
@ -1730,21 +1729,21 @@ describe('Core Helpers', function () {
it('should output absolute path if absolute is set', function () {
// no trailing slash
configUpdate({url: 'http://testurl.com'});
config.set({url: 'http://testurl.com'});
rendered = helpers.admin_url({'hash': {absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/ghost');
// test trailing slash
configUpdate({url: 'http://testurl.com/'});
config.set({url: 'http://testurl.com/'});
rendered = helpers.admin_url({'hash': {absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/ghost');
});
it('should output absolute path with subdirectory', function () {
configUpdate({url: 'http://testurl.com/blog'});
config.set({url: 'http://testurl.com/blog'});
rendered = helpers.admin_url({'hash': {absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/blog/ghost');
@ -1757,27 +1756,27 @@ describe('Core Helpers', function () {
});
it('should output the absolute path to frontend if both are set', function () {
configUpdate({url: 'http://testurl.com'});
config.set({url: 'http://testurl.com'});
rendered = helpers.admin_url({'hash': {frontend: true, absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/');
configUpdate({url: 'http://testurl.com/'});
config.set({url: 'http://testurl.com/'});
rendered = helpers.admin_url({'hash': {frontend: true, absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/');
});
it('should output the path to frontend with subdirectory', function () {
configUpdate({url: 'http://testurl.com/blog/'});
config.set({url: 'http://testurl.com/blog/'});
rendered = helpers.admin_url({'hash': {frontend: true}});
should.exist(rendered);
rendered.should.equal('/blog/');
});
it('should output the absolute path to frontend with subdirectory', function () {
configUpdate({url: 'http://testurl.com/blog/'});
config.set({url: 'http://testurl.com/blog/'});
rendered = helpers.admin_url({'hash': {frontend: true, absolute: true}});
should.exist(rendered);
rendered.should.equal('http://testurl.com/blog/');
@ -1862,7 +1861,7 @@ describe('Core Helpers', function () {
var configUrl = config.url;
afterEach(function () {
configUpdate({url: configUrl});
config.set({url: configUrl});
});
it('is loaded', function () {

View file

@ -7,7 +7,6 @@ var fs = require('fs-extra'),
rewire = require('rewire'),
_ = require('lodash'),
config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig'),
localfilesystem = rewire('../../server/storage/localfilesystem');
// To stop jshint complaining
@ -19,7 +18,7 @@ describe('Local File System Storage', function () {
overrideConfig = function (newConfig) {
var existingConfig = localfilesystem.__get__('config'),
updatedConfig = _.extend(existingConfig, newConfig);
configUpdate(updatedConfig);
config.set(updatedConfig);
localfilesystem.__set__('config', updatedConfig);
};