This aims to speed up both the ghost application and tests by

migration from usage of config() to just an object of config.

no relevant issue

- Change 'loadConfig' task to 'ensureConfig' to more accurately reflect
what it is actually doing.  Its sole purpose is to make sure a `config.js`
 file exists, and as such the name now reflects that purpose.

- Update config/index.js to export the ghostConfig object directly
so that it can be accessed from other modules

- Update all references of config(). to config.
This was a blind global find all and replace, treat it as such.

- Fixes to tests to support new config access method

- Allow each test to still work when invoked invidually
This commit is contained in:
Harry Wolff 2014-07-17 10:33:21 -04:00
parent a620e9017e
commit be37070fb6
43 changed files with 307 additions and 314 deletions

View File

@ -11,7 +11,6 @@ var path = require('path'),
_ = require('lodash'),
buildDirectory = path.resolve(process.cwd(), '.build'),
distDirectory = path.resolve(process.cwd(), '.dist'),
bootstrap = require('./core/bootstrap'),
// ## Build File Patterns
// A list of files and patterns to include when creating a release zip.
@ -160,7 +159,9 @@ var path = require('path'),
// #### All Unit tests
unit: {
src: ['core/test/unit/**/*_spec.js']
src: [
'core/test/unit/**/*_spec.js'
]
},
// ##### Groups of unit tests
@ -208,7 +209,9 @@ var path = require('path'),
// #### All Route tests
routes: {
src: ['core/test/functional/routes/**/*_test.js']
src: [
'core/test/functional/routes/**/*_test.js'
]
}
},
@ -537,12 +540,13 @@ var path = require('path'),
cfg.express.test.options.node_env = process.env.NODE_ENV;
});
// #### Load Config *(Utility Task)*
// #### Ensure Config *(Utility Task)*
// Make sure that we have a `config.js` file when running tests
// 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('loadConfig', function () {
var done = this.async();
grunt.registerTask('ensureConfig', function () {
var bootstrap = require('./core/bootstrap'),
done = this.async();
bootstrap().then(function () {
done();
}).catch(function (err) {
@ -607,7 +611,7 @@ var path = require('path'),
// Unit tests do **not** touch the database.
// A coverage report can be generated for these tests using the `grunt test-coverage` task.
grunt.registerTask('test-unit', 'Run unit tests (mocha)',
['clean:test', 'setTestEnv', 'loadConfig', 'mochacli:unit']);
['clean:test', 'setTestEnv', 'ensureConfig', 'mochacli:unit']);
// ### Integration tests *(sub task)*
// `grunt test-integration` will run just the integration tests
@ -636,7 +640,7 @@ var path = require('path'),
//
// A coverage report can be generated for these tests using the `grunt test-coverage` task.
grunt.registerTask('test-integration', 'Run integration tests (mocha + db access)',
['clean:test', 'setTestEnv', 'loadConfig', 'mochacli:integration']);
['clean:test', 'setTestEnv', 'ensureConfig', 'mochacli:integration']);
// ### Route tests *(sub task)*
// `grunt test-routes` will run just the route tests
@ -657,7 +661,7 @@ var path = require('path'),
// are working as expected, including checking the headers and status codes received. It is very easy and
// quick to test many permutations of routes / urls in the system.
grunt.registerTask('test-routes', 'Run functional route tests (mocha)',
['clean:test', 'setTestEnv', 'loadConfig', 'mochacli:routes']);
['clean:test', 'setTestEnv', 'ensureConfig', 'mochacli:routes']);
// ### Functional tests for the setup process
// `grunt test-functional-setup will run just the functional tests for the setup page.
@ -665,7 +669,7 @@ var path = require('path'),
// Setup only works with a brand new database, so it needs to run isolated from the rest of
// the functional tests.
grunt.registerTask('test-functional-setup', 'Run functional tests for setup',
['clean:test', 'setTestEnv', 'loadConfig', 'cleanDatabase', 'express:test',
['clean:test', 'setTestEnv', 'ensureConfig', 'cleanDatabase', 'express:test',
'spawnCasperJS:setup', 'express:test:stop']
);
@ -688,7 +692,7 @@ var path = require('path'),
// The purpose of the functional tests is to ensure that Ghost is working as is expected from a user perspective
// including buttons and other important interactions in the admin UI.
grunt.registerTask('test-functional', 'Run functional interface tests (CasperJS)',
['clean:test', 'setTestEnv', 'loadConfig', 'cleanDatabase', 'express:test', 'spawnCasperJS', 'express:test:stop',
['clean:test', 'setTestEnv', 'ensureConfig', 'cleanDatabase', 'express:test', 'spawnCasperJS', 'express:test:stop',
'test-functional-setup']
);
@ -702,7 +706,7 @@ var path = require('path'),
//
// Key areas for coverage are: helpers and theme elements, apps / GDK, the api and model layers.
grunt.registerTask('test-coverage', 'Generate unit and integration (mocha) tests coverage report',
['clean:test', 'setTestEnv', 'loadConfig', 'shell:coverage']);
['clean:test', 'setTestEnv', 'ensureConfig', 'shell:coverage']);
// ## Building assets

6
core/bootstrap.js vendored
View File

@ -11,8 +11,8 @@ var fs = require('fs'),
errors = require('./server/errors'),
config = require('./server/config'),
appRoot = config().paths.appRoot,
configExample = config().paths.configExample,
appRoot = config.paths.appRoot,
configExample = config.paths.configExample,
configFile;
function readConfigFile(envVal) {
@ -122,7 +122,7 @@ function loadConfig(configFilePath) {
// Allow config file path to be taken from, in order of importance:
// environment process, passed in value, default location
configFile = process.env.GHOST_CONFIG || configFilePath || config().paths.config;
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. */

View File

@ -45,7 +45,7 @@ authentication = {
var dbHash = response.settings[0].value;
return dataProvider.User.generateResetToken(email, expires, dbHash);
}).then(function (resetToken) {
var baseUrl = config().forceAdminSSL ? (config().urlSSL || config().url) : config().url,
var baseUrl = config.forceAdminSSL ? (config.urlSSL || config.url) : config.url,
siteLink = '<a href="' + baseUrl + '">' + baseUrl + '</a>',
resetUrl = baseUrl.replace(/\/$/, '') + '/ghost/reset/' + resetToken + '/',
resetLink = '<a href="' + resetUrl + '">' + resetUrl + '</a>',
@ -216,7 +216,7 @@ authentication = {
to: setupUser.email,
subject: 'Your New Ghost Blog',
html: '<p><strong>Hello!</strong></p>' +
'<p>Good news! You\'ve successfully created a brand new Ghost blog over on ' + config().url + '</p>' +
'<p>Good news! You\'ve successfully created a brand new Ghost blog over on ' + config.url + '</p>' +
'<p>You can log in to your admin account with the following details:</p>' +
'<p> Email Address: ' + setupUser.email + '<br>' +
'Password: The password you chose when you signed up</p>' +

View File

@ -56,7 +56,7 @@ mail = {
sendTest: function (object, options) {
var html = '<p><strong>Hello there!</strong></p>' +
'<p>Excellent!' +
' You\'ve successfully setup your email config for your Ghost blog over on ' + config().url + '</p>' +
' You\'ve successfully setup your email config for your Ghost blog over on ' + config.url + '</p>' +
'<p>If you hadn\'t, you wouldn\'t be reading this email, but you are, so it looks like all is well :)</p>' +
'<p>xoxo</p>' +
'<p>Team Ghost<br>' +

View File

@ -135,11 +135,11 @@ readSettingsResult = function (settingsModels) {
return memo;
}, {}),
themes = config().paths.availableThemes,
apps = config().paths.availableApps,
themes = config.paths.availableThemes,
apps = config.paths.availableApps,
res;
if (settings.activeTheme) {
if (settings.activeTheme && themes) {
res = filterPaths(themes, settings.activeTheme.value);
settings.availableThemes = {
@ -149,7 +149,7 @@ readSettingsResult = function (settingsModels) {
};
}
if (settings.activeApps) {
if (settings.activeApps && apps) {
res = filterPaths(apps, JSON.parse(settings.activeApps.value));
settings.availableApps = {
@ -201,7 +201,7 @@ populateDefaultSetting = function (key) {
// Add to the settings cache
return updateSettingsCache(readResult).then(function () {
// Update theme with the new settings
return config.theme.update(settings, config().url);
return config.theme.update(settings, config.url);
}).then(function () {
// Get the result from the cache with permission checks
return defaultSetting;
@ -379,7 +379,7 @@ settings = {
var readResult = readSettingsResult(result);
return updateSettingsCache(readResult).then(function () {
return config.theme.update(settings, config().url);
return config.theme.update(settings, config.url);
}).then(function () {
return settingsResult(readResult, type);
});

View File

@ -27,7 +27,7 @@ themes = {
return canThis(options.context).browse.theme().then(function () {
return when.all([
settings.read({key: 'activeTheme', context: {internal: true}}),
config().paths.availableThemes
config.paths.availableThemes
]).then(function (result) {
var activeTheme = result[0].settings[0].value,
availableThemes = result[1],

View File

@ -176,7 +176,7 @@ users = {
dbHash = response.settings[0].value;
return dataProvider.User.generateResetToken(user.email, expires, dbHash);
}).then(function (resetToken) {
var baseUrl = config().forceAdminSSL ? (config().urlSSL || config().url) : config().url,
var baseUrl = config.forceAdminSSL ? (config.urlSSL || config.url) : config.url,
siteLink = '<a href="' + baseUrl + '">' + baseUrl + '</a>',
resetUrl = baseUrl.replace(/\/$/, '') + '/ghost/signup/' + resetToken + '/',
resetLink = '<a href="' + resetUrl + '">' + resetUrl + '</a>',

View File

@ -11,7 +11,7 @@ var path = require('path'),
// Get the full path to an app by name
function getAppAbsolutePath(name) {
return path.join(config().paths.appPath, name);
return path.join(config.paths.appPath, name);
}
// Get a relative path to the given apps root, defaults

View File

@ -14,6 +14,8 @@ var path = require('path'),
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?
@ -25,7 +27,7 @@ function getSocket() {
}
function updateConfig(config) {
var localPath,
var localPath = '',
contentPath,
subdir;
@ -53,7 +55,7 @@ function updateConfig(config) {
// Otherwise default to default content path location
contentPath = ghostConfig.paths.contentPath || path.resolve(appRoot, 'content');
if (!knexInstance && ghostConfig.database) {
if (!knexInstance && ghostConfig.database && ghostConfig.database.client) {
knexInstance = knex(ghostConfig.database);
}
@ -80,8 +82,8 @@ function updateConfig(config) {
'lang': path.join(corePath, '/shared/lang/'),
'debugPath': subdir + '/ghost/debug/',
'availableThemes': ghostConfig.paths.availableThemes || [],
'availableApps': ghostConfig.paths.availableApps || [],
'availableThemes': ghostConfig.paths.availableThemes || {},
'availableApps': ghostConfig.paths.availableApps || {},
'builtScriptPath': path.join(corePath, 'built/scripts/')
}
});
@ -90,8 +92,6 @@ function updateConfig(config) {
// configUrl object to maintain
// clean depedency tree
configUrl.setConfig(ghostConfig);
return ghostConfig;
}
function initConfig(rawConfig) {
@ -99,7 +99,7 @@ function initConfig(rawConfig) {
// 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
ghostConfig = updateConfig(rawConfig);
updateConfig(rawConfig);
return when.all([requireTree(ghostConfig.paths.themePath), requireTree(ghostConfig.paths.appPath)]).then(function (paths) {
ghostConfig.paths.availableThemes = paths[0];
@ -108,23 +108,14 @@ function initConfig(rawConfig) {
});
}
// Returns NODE_ENV config object
function config() {
// @TODO: get rid of require statement.
// This is currently needed for tests to load config file
// successfully. While running application we should never
// have to directly delegate to the config.js file.
if (_.isEmpty(ghostConfig)) {
try {
ghostConfig = require(path.resolve(__dirname, '../../../', 'config.js'))[process.env.NODE_ENV] || {};
} catch (ignore) {/*jslint strict: true */}
ghostConfig = updateConfig(ghostConfig);
}
return ghostConfig;
if (testingEnvs.indexOf(process.env.NODE_ENV) > -1) {
defaultConfig = require('../../../config.example')[process.env.NODE_ENV];
}
module.exports = config;
// Init config
updateConfig(defaultConfig);
module.exports = ghostConfig;
module.exports.init = initConfig;
module.exports.theme = theme;
module.exports.getSocket = getSocket;

View File

@ -91,14 +91,14 @@ frontendControllers = {
// No negative pages, or page 1
if (isNaN(pageParam) || pageParam < 1 || (pageParam === 1 && req.route.path === '/page/:page/')) {
return res.redirect(config().paths.subdir + '/');
return res.redirect(config.paths.subdir + '/');
}
return getPostPage(options).then(function (page) {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > page.meta.pagination.pages) {
return res.redirect(page.meta.pagination.pages === 1 ? config().paths.subdir + '/' : (config().paths.subdir + '/page/' + page.meta.pagination.pages + '/'));
return res.redirect(page.meta.pagination.pages === 1 ? config.paths.subdir + '/' : (config.paths.subdir + '/page/' + page.meta.pagination.pages + '/'));
}
setReqCtx(req, page.posts);
@ -119,7 +119,7 @@ frontendControllers = {
// Get url for tag page
function tagUrl(tag, page) {
var url = config().paths.subdir + '/tag/' + tag + '/';
var url = config.paths.subdir + '/tag/' + tag + '/';
if (page && page > 1) {
url += 'page/' + page + '/';
@ -148,7 +148,7 @@ frontendControllers = {
filters.doFilter('prePostsRender', page.posts).then(function (posts) {
api.settings.read({key: 'activeTheme', context: {internal: true}}).then(function (response) {
var activeTheme = response.settings[0],
paths = config().paths.availableThemes[activeTheme.value],
paths = config.paths.availableThemes[activeTheme.value],
view = paths.hasOwnProperty('tag.hbs') ? 'tag' : 'index',
// Format data for template
@ -277,7 +277,7 @@ frontendControllers = {
function render() {
// If we're ready to render the page but the last param is 'edit' then we'll send you to the edit page.
if (params.edit === 'edit') {
return res.redirect(config().paths.subdir + '/ghost/editor/' + post.id + '/');
return res.redirect(config.paths.subdir + '/ghost/editor/' + post.id + '/');
} else if (params.edit !== undefined) {
// reject with type: 'NotFound'
return when.reject(new errors.NotFoundError());
@ -288,7 +288,7 @@ frontendControllers = {
filters.doFilter('prePostsRender', post).then(function (post) {
api.settings.read({key: 'activeTheme', context: {internal: true}}).then(function (response) {
var activeTheme = response.settings[0],
paths = config().paths.availableThemes[activeTheme.value],
paths = config.paths.availableThemes[activeTheme.value],
view = template.getThemeViewForPost(paths, post);
res.render(view, {post: post});
@ -358,9 +358,9 @@ frontendControllers = {
if (isNaN(pageParam) || pageParam < 1 ||
(pageParam === 1 && (req.route.path === '/rss/:page/' || req.route.path === '/tag/:slug/rss/:page/'))) {
if (tagParam !== undefined) {
return res.redirect(config().paths.subdir + '/tag/' + tagParam + '/rss/');
return res.redirect(config.paths.subdir + '/tag/' + tagParam + '/rss/');
} else {
return res.redirect(config().paths.subdir + '/rss/');
return res.redirect(config.paths.subdir + '/rss/');
}
}
@ -410,9 +410,9 @@ frontendControllers = {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > maxPage) {
if (tagParam) {
return res.redirect(config().paths.subdir + '/tag/' + tagParam + '/rss/' + maxPage + '/');
return res.redirect(config.paths.subdir + '/tag/' + tagParam + '/rss/' + maxPage + '/');
} else {
return res.redirect(config().paths.subdir + '/rss/' + maxPage + '/');
return res.redirect(config.paths.subdir + '/rss/' + maxPage + '/');
}
}

View File

@ -33,7 +33,7 @@ exporter = function () {
tables = results[1],
selectOps = _.map(tables, function (name) {
if (excludedTables.indexOf(name) < 0) {
return config().database.knex(name).select();
return config.database.knex(name).select();
}
});

View File

@ -6,7 +6,7 @@ var _ = require('lodash'),
errors = require('../../errors'),
sequence = require('when/sequence'),
commands = require('./commands'),
commands = require('./commands'),
versioning = require('../versioning'),
models = require('../../models'),
fixtures = require('../fixtures'),
@ -44,7 +44,7 @@ backupDatabase = function backupDatabase() {
logInfo('Creating database backup');
return dataExport().then(function (exportedData) {
// Save the exported data to the file system for download
var fileName = path.resolve(config().paths.contentPath + '/data/' + dataExport.fileName());
var fileName = path.resolve(config.paths.contentPath + '/data/' + dataExport.fileName());
return nodefn.call(fs.writeFile, fileName, JSON.stringify(exportedData)).then(function () {
logInfo('Database backup written to: ' + fileName);

View File

@ -12,7 +12,7 @@ var _ = require('lodash'),
checkPostTable;
doRawAndFlatten = function doRaw(query, flattenFn) {
return config().database.knex.raw(query).then(function (response) {
return config.database.knex.raw(query).then(function (response) {
return _.flatten(flattenFn(response));
});
};
@ -40,10 +40,10 @@ getColumns = function getColumns(table) {
// data type text instead of mediumtext.
// For details see: https://github.com/TryGhost/Ghost/issues/1947
checkPostTable = function checkPostTable() {
return config().database.knex.raw('SHOW FIELDS FROM posts where Field ="html" OR Field = "markdown"').then(function (response) {
return config.database.knex.raw('SHOW FIELDS FROM posts where Field ="html" OR Field = "markdown"').then(function (response) {
return _.flatten(_.map(response[0], function (entry) {
if (entry.Type.toLowerCase() !== 'mediumtext') {
return config().database.knex.raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT').then(function () {
return config.database.knex.raw('ALTER TABLE posts MODIFY ' + entry.Field + ' MEDIUMTEXT').then(function () {
return when.resolve();
});
}

View File

@ -11,7 +11,7 @@ var _ = require('lodash'),
doRawFlattenAndPluck = function doRaw(query, name) {
return config().database.knex.raw(query).then(function (response) {
return config.database.knex.raw(query).then(function (response) {
return _.flatten(_.pluck(response.rows, name));
});
};

View File

@ -11,7 +11,7 @@ var _ = require('lodash'),
doRaw = function doRaw(query, fn) {
return config().database.knex.raw(query).then(function (response) {
return config.database.knex.raw(query).then(function (response) {
return fn(response);
});
};

View File

@ -44,28 +44,28 @@ function addTableColumn(tablename, table, columnname) {
}
function addColumn(table, column) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
return dbConfig.knex.schema.table(table, function (t) {
addTableColumn(table, t, column);
});
}
function addUnique(table, column) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
return dbConfig.knex.schema.table(table, function (table) {
table.unique(column);
});
}
function dropUnique(table, column) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
return dbConfig.knex.schema.table(table, function (table) {
table.dropUnique(column);
});
}
function createTable(table) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
return dbConfig.knex.schema.createTable(table, function (t) {
var columnKeys = _.keys(schema[table]);
_.each(columnKeys, function (column) {
@ -75,12 +75,12 @@ function createTable(table) {
}
function deleteTable(table) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
return dbConfig.knex.schema.dropTableIfExists(table);
}
function getTables() {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
var client = dbConfig.client;
if (_.contains(_.keys(clients), client)) {
@ -91,7 +91,7 @@ function getTables() {
}
function getIndexes(table) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
var client = dbConfig.client;
if (_.contains(_.keys(clients), client)) {
@ -102,7 +102,7 @@ function getIndexes(table) {
}
function getColumns(table) {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
var client = dbConfig.client;
if (_.contains(_.keys(clients), client)) {
@ -113,7 +113,7 @@ function getColumns(table) {
}
function checkTables() {
dbConfig = dbConfig || config().database;
dbConfig = dbConfig || config.database;
var client = dbConfig.client;
if (client === 'mysql') {

View File

@ -101,13 +101,13 @@ validateSettings = function (defaultSettings, model) {
// A Promise that will resolve to an object with a property for each installed theme.
// This is necessary because certain configuration data is only available while Ghost
// is running and at times the validations are used when it's not (e.g. tests)
availableThemes = requireTree(config().paths.themePath);
availableThemes = requireTree(config.paths.themePath);
validateActiveTheme = function (themeName) {
// If Ghost is running and its availableThemes collection exists
// give it priority.
if (Object.keys(config().paths.availableThemes).length > 0) {
availableThemes = when(config().paths.availableThemes);
if (config.paths.availableThemes && Object.keys(config.paths.availableThemes).length > 0) {
availableThemes = when(config.paths.availableThemes);
}
return availableThemes.then(function (themes) {

View File

@ -23,7 +23,7 @@ function getDefaultDatabaseVersion() {
// The migration version number according to the database
// This is what the database is currently at and may need to be updated
function getDatabaseVersion() {
var knex = config().database.knex;
var knex = config.database.knex;
return knex.schema.hasTable('settings').then(function (exists) {
// Check for the current version from the settings table
@ -54,7 +54,7 @@ function getDatabaseVersion() {
}
function setDatabaseVersion() {
return config().database.knex('settings')
return config.database.knex('settings')
.where('key', 'databaseVersion')
.update({ 'value': defaultDatabaseVersion });
}

View File

@ -17,7 +17,7 @@ var _ = require('lodash'),
errors,
// Paths for views
defaultErrorTemplatePath = path.resolve(config().paths.adminViews, 'user-error.hbs'),
defaultErrorTemplatePath = path.resolve(config.paths.adminViews, 'user-error.hbs'),
userErrorTemplateExists = false;
// This is not useful but required for jshint
@ -28,7 +28,7 @@ colors.setTheme({silly: 'rainbow'});
*/
errors = {
updateActiveTheme: function (activeTheme) {
userErrorTemplateExists = config().paths.availableThemes[activeTheme].hasOwnProperty('error.hbs');
userErrorTemplateExists = config.paths.availableThemes[activeTheme].hasOwnProperty('error.hbs');
},
throwError: function (err) {

View File

@ -100,7 +100,7 @@ coreHelpers.encode = function (context, str) {
//
coreHelpers.page_url = function (context, block) {
/*jshint unused:false*/
var url = config().paths.subdir;
var url = config.paths.subdir;
if (this.tagSlug !== undefined) {
url += '/tag/' + this.tagSlug;
@ -173,7 +173,7 @@ coreHelpers.asset = function (context, options) {
var output = '',
isAdmin = options && options.hash && options.hash.ghost;
output += config().paths.subdir + '/';
output += config.paths.subdir + '/';
if (!context.match(/^favicon\.ico$/) && !context.match(/^shared/) && !context.match(/^asset/)) {
if (isAdmin) {
@ -349,8 +349,8 @@ coreHelpers.excerpt = function (options) {
// Returns the config value for fileStorage.
coreHelpers.file_storage = function (context, options) {
/*jshint unused:false*/
if (config().hasOwnProperty('fileStorage')) {
return config().fileStorage.toString();
if (config.hasOwnProperty('fileStorage')) {
return config.fileStorage.toString();
}
return 'true';
};
@ -363,8 +363,8 @@ coreHelpers.file_storage = function (context, options) {
// Returns the config value for apps.
coreHelpers.apps = function (context, options) {
/*jshint unused:false*/
if (config().hasOwnProperty('apps')) {
return config().apps.toString();
if (config.hasOwnProperty('apps')) {
return config.apps.toString();
}
return 'false';
};
@ -374,7 +374,7 @@ coreHelpers.ghost_script_tags = function () {
scriptList = _.map(scriptList, function (fileName) {
return scriptTemplate({
source: config().paths.subdir + '/ghost/scripts/' + fileName,
source: config.paths.subdir + '/ghost/scripts/' + fileName,
version: coreHelpers.assetHash
});
});
@ -416,7 +416,7 @@ coreHelpers.body_class = function (options) {
return api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function (response) {
var activeTheme = response.settings[0],
paths = config().paths.availableThemes[activeTheme.value],
paths = config.paths.availableThemes[activeTheme.value],
view;
if (post) {
@ -494,7 +494,7 @@ coreHelpers.ghost_foot = function (options) {
foot = [];
foot.push(scriptTemplate({
source: config().paths.subdir + '/public/' + jquery,
source: config.paths.subdir + '/public/' + jquery,
version: coreHelpers.assetHash
}));

View File

@ -41,7 +41,7 @@ function doFirstRun() {
'</strong>environment.',
'Your URL is set to',
'<strong>' + config().url + '</strong>.',
'<strong>' + config.url + '</strong>.',
'See <a href="http://docs.ghost.org/">http://docs.ghost.org</a> for instructions.'
];
@ -76,7 +76,7 @@ function initDbHashAndFirstRun() {
// any are missing.
function builtFilesExist() {
var deferreds = [],
location = config().paths.builtScriptPath,
location = config.paths.builtScriptPath,
fileNames = helpers.scriptFiles.ember;
@ -127,7 +127,7 @@ function ghostStartMessages() {
console.log(
"Ghost is running...".green,
"\nYour blog is now available on",
config().url,
config.url,
"\nCtrl+C to shut down".grey
);
@ -143,9 +143,9 @@ function ghostStartMessages() {
console.log(
("Ghost is running in " + process.env.NODE_ENV + "...").green,
"\nListening on",
config.getSocket() || config().server.host + ':' + config().server.port,
config.getSocket() || config.server.host + ':' + config.server.port,
"\nUrl configured as:",
config().url,
config.url,
"\nCtrl+C to shut down".grey
);
// ensure that Ghost exits correctly on Ctrl+C
@ -231,7 +231,7 @@ function init(server) {
}).then(function () {
// We must pass the api.settings object
// into this method due to circular dependencies.
return config.theme.update(api.settings, config().url);
return config.theme.update(api.settings, config.url);
}).then(function () {
return when.join(
// Check for or initialise a dbHash.
@ -253,7 +253,7 @@ function init(server) {
express['static'].mime.define({'application/font-woff': ['woff']});
// enabled gzip compression by default
if (config().server.compress !== false) {
if (config.server.compress !== false) {
server.use(compress());
}
@ -271,11 +271,11 @@ function init(server) {
middleware(server, dbHash);
// Log all theme errors and warnings
_.each(config().paths.availableThemes._messages.errors, function (error) {
_.each(config.paths.availableThemes._messages.errors, function (error) {
errors.logError(error.message, error.context, error.help);
});
_.each(config().paths.availableThemes._messages.warns, function (warn) {
_.each(config.paths.availableThemes._messages.warns, function (warn) {
errors.logWarn(warn.message, warn.context, warn.help);
});
@ -295,8 +295,8 @@ function init(server) {
} else {
httpServer = server.listen(
config().server.port,
config().server.host
config.server.port,
config.server.host
);
}

View File

@ -15,7 +15,7 @@ function GhostMailer(opts) {
GhostMailer.prototype.init = function () {
var self = this;
self.state = {};
if (config().mail && config().mail.transport) {
if (config.mail && config.mail.transport) {
this.createTransport();
return when.resolve();
}
@ -53,17 +53,17 @@ GhostMailer.prototype.detectSendmail = function () {
};
GhostMailer.prototype.createTransport = function () {
this.transport = nodemailer.createTransport(config().mail.transport, _.clone(config().mail.options) || {});
this.transport = nodemailer.createTransport(config.mail.transport, _.clone(config.mail.options) || {});
};
GhostMailer.prototype.fromAddress = function () {
var from = config().mail && config().mail.fromaddress,
var from = config.mail && config.mail.fromaddress,
domain;
if (!from) {
// Extract the domain name from url set in config.js
domain = config().url.match(new RegExp("^https?://([^/:?#]+)(?:[/:?#]|$)", "i"));
domain = config.url.match(new RegExp("^https?://([^/:?#]+)(?:[/:?#]|$)", "i"));
domain = domain && domain[1];
// Default to ghost@[blog.url]

View File

@ -42,17 +42,17 @@ function ghostLocals(req, res, next) {
res.locals = res.locals || {};
res.locals.version = packageInfo.version;
// relative path from the URL, not including subdir
res.locals.relativeUrl = req.path.replace(config().paths.subdir, '');
res.locals.relativeUrl = req.path.replace(config.paths.subdir, '');
next();
}
function initThemeData(secure) {
var themeConfig = config.theme();
if (secure && config().urlSSL) {
if (secure && config.urlSSL) {
// For secure requests override .url property with the SSL version
themeConfig = _.clone(themeConfig);
themeConfig.url = config().urlSSL.replace(/\/$/, '');
themeConfig.url = config.urlSSL.replace(/\/$/, '');
}
return themeConfig;
}
@ -61,13 +61,13 @@ function initThemeData(secure) {
// Helper for manageAdminAndTheme
function activateTheme(activeTheme) {
var hbsOptions,
themePartials = path.join(config().paths.themePath, activeTheme, 'partials');
themePartials = path.join(config.paths.themePath, activeTheme, 'partials');
// clear the view cache
expressServer.cache = {};
// set view engine
hbsOptions = { partialsDir: [ config().paths.helperTemplates ] };
hbsOptions = { partialsDir: [ config.paths.helperTemplates ] };
fs.stat(themePartials, function (err, stats) {
// Check that the theme has a partials directory before trying to use it
@ -89,18 +89,18 @@ function activateTheme(activeTheme) {
// Uses the URL to detect whether this response should be an admin response
// This is used to ensure the right content is served, and is not for security purposes
function decideContext(req, res, next) {
res.isAdmin = req.url.lastIndexOf(config().paths.subdir + '/ghost/', 0) === 0;
res.isAdmin = req.url.lastIndexOf(config.paths.subdir + '/ghost/', 0) === 0;
if (res.isAdmin) {
expressServer.enable('admin');
expressServer.engine('hbs', expressServer.get('admin view engine'));
expressServer.set('views', config().paths.adminViews);
expressServer.set('views', config.paths.adminViews);
} else {
expressServer.disable('admin');
var themeData = initThemeData(req.secure);
hbs.updateTemplateOptions({ data: {blog: themeData} });
expressServer.engine('hbs', expressServer.get('theme view engine'));
expressServer.set('views', path.join(config().paths.themePath, expressServer.get('activeTheme')));
expressServer.set('views', path.join(config.paths.themePath, expressServer.get('activeTheme')));
}
// Pass 'secure' flag to the view engine
@ -120,7 +120,7 @@ function updateActiveTheme(req, res, next) {
// Check if the theme changed
if (activeTheme.value !== expressServer.get('activeTheme')) {
// Change theme
if (!config().paths.availableThemes.hasOwnProperty(activeTheme.value)) {
if (!config.paths.availableThemes.hasOwnProperty(activeTheme.value)) {
if (!res.isAdmin) {
// Throw an error if the theme is not available, but not on the admin UI
return errors.throwError('The currently active theme ' + activeTheme.value + ' is missing.');
@ -144,7 +144,7 @@ function redirectToSetup(req, res, next) {
api.authentication.isSetup().then(function (exists) {
if (!exists.setup[0].status && !req.path.match(/\/ghost\/setup\//)) {
return res.redirect(config().paths.subdir + '/ghost/setup/');
return res.redirect(config.paths.subdir + '/ghost/setup/');
}
next();
}).otherwise(function (err) {
@ -153,8 +153,8 @@ function redirectToSetup(req, res, next) {
}
function isSSLrequired(isAdmin) {
var forceSSL = url.parse(config().url).protocol === 'https:' ? true : false,
forceAdminSSL = (isAdmin && config().forceAdminSSL);
var forceSSL = url.parse(config.url).protocol === 'https:' ? true : false,
forceAdminSSL = (isAdmin && config.forceAdminSSL);
if (forceSSL || forceAdminSSL) {
return true;
}
@ -166,7 +166,7 @@ function isSSLrequired(isAdmin) {
function checkSSL(req, res, next) {
if (isSSLrequired(res.isAdmin)) {
if (!req.secure) {
var forceAdminSSL = config().forceAdminSSL,
var forceAdminSSL = config.forceAdminSSL,
redirectUrl;
// Check if forceAdminSSL: { redirect: false } is set, which means
@ -175,7 +175,7 @@ function checkSSL(req, res, next) {
return res.send(403);
}
redirectUrl = url.parse(config().urlSSL || config().url);
redirectUrl = url.parse(config.urlSSL || config.url);
return res.redirect(301, url.format({
protocol: 'https:',
hostname: redirectUrl.hostname,
@ -192,7 +192,7 @@ function checkSSL(req, res, next) {
// Handle requests to robots.txt and cache file
function robots() {
var content, // file cache
filePath = path.join(config().paths.corePath, '/shared/robots.txt');
filePath = path.join(config.paths.corePath, '/shared/robots.txt');
return function robots(req, res, next) {
if ('/robots.txt' === req.url) {
@ -224,9 +224,9 @@ function robots() {
}
setupMiddleware = function (server) {
var logging = config().logging,
subdir = config().paths.subdir,
corePath = config().paths.corePath,
var logging = config.logging,
subdir = config.paths.subdir,
corePath = config.paths.corePath,
oauthServer = oauth2orize.createServer();
// silence JSHint without disabling unused check for the whole file

View File

@ -43,7 +43,7 @@ var middleware = {
// SubPath is the url path starting after any default subdirectories
// it is stripped of anything after the two levels `/ghost/.*?/` as the reset link has an argument
path = req.path.substring(config().paths.subdir.length);
path = req.path.substring(config.paths.subdir.length);
/*jslint regexp:true, unparam:true*/
subPath = path.replace(/^(\/.*?\/.*?\/)(.*)?/, function (match, a) {
return a;
@ -130,7 +130,7 @@ var middleware = {
api.settings.read({context: {internal: true}, key: 'activeTheme'}).then(function (response) {
var activeTheme = response.settings[0];
express['static'](path.join(config().paths.themePath, activeTheme.value), {maxAge: ONE_YEAR_MS})(req, res, next);
express['static'](path.join(config.paths.themePath, activeTheme.value), {maxAge: ONE_YEAR_MS})(req, res, next);
});
},

View File

@ -21,7 +21,7 @@ var bookshelf = require('bookshelf'),
// ### ghostBookshelf
// Initializes a new Bookshelf instance called ghostBookshelf, for reference elsewhere in Ghost.
ghostBookshelf = bookshelf(config().database.knex);
ghostBookshelf = bookshelf(config.database.knex);
// Load the registry plugin, which helps us avoid circular dependencies
ghostBookshelf.plugin('registry');

View File

@ -9,7 +9,7 @@ var admin = require('../controllers/admin'),
adminRoutes = function (middleware) {
var router = express.Router(),
subdir = config().paths.subdir;
subdir = config.paths.subdir;
// ### Admin routes
router.get(/^\/(logout|signout)\/$/, function redirect(req, res) {

View File

@ -9,7 +9,7 @@ var frontend = require('../controllers/frontend'),
frontendRoutes = function () {
var router = express.Router(),
subdir = config().paths.subdir;
subdir = config.paths.subdir;
// ### Frontend routes
router.get('/rss/', frontend.rss);

View File

@ -20,7 +20,7 @@ localFileStore = _.extend(baseStore, {
// - returns a promise which ultimately returns the full url to the uploaded image
'save': function (image) {
var saved = when.defer(),
targetDir = this.getTargetDir(config().paths.imagesPath),
targetDir = this.getTargetDir(config.paths.imagesPath),
targetFilename;
this.getUniqueFileName(this, image, targetDir).then(function (filename) {
@ -31,7 +31,7 @@ localFileStore = _.extend(baseStore, {
}).then(function () {
// The src for the image must be in URI format, not a file system path, which in Windows uses \
// For local file system storage can use relative path so add a slash
var fullUrl = (config().paths.subdir + '/' + config().paths.imagesRelPath + '/' + path.relative(config().paths.imagesPath, targetFilename)).replace(new RegExp('\\' + path.sep, 'g'), '/');
var fullUrl = (config.paths.subdir + '/' + config.paths.imagesRelPath + '/' + path.relative(config.paths.imagesPath, targetFilename)).replace(new RegExp('\\' + path.sep, 'g'), '/');
return saved.resolve(fullUrl);
}).otherwise(function (e) {
errors.logError(e);
@ -58,7 +58,7 @@ localFileStore = _.extend(baseStore, {
ONE_YEAR_MS = 365 * 24 * ONE_HOUR_MS;
// For some reason send divides the max age number by 1000
return express['static'](config().paths.imagesPath, {maxAge: ONE_YEAR_MS});
return express['static'](config.paths.imagesPath, {maxAge: ONE_YEAR_MS});
}
});

View File

@ -49,7 +49,7 @@ function updateCheckError(error) {
function updateCheckData() {
var data = {},
ops = [],
mailConfig = config().mail;
mailConfig = config.mail;
ops.push(api.settings.read(_.extend(internal, {key: 'dbHash'})).otherwise(errors.rejectError));
ops.push(api.settings.read(_.extend(internal, {key: 'activeTheme'})).otherwise(errors.rejectError));
@ -71,7 +71,7 @@ function updateCheckData() {
data.ghost_version = currentVersion;
data.node_version = process.versions.node;
data.env = process.env.NODE_ENV;
data.database_type = config().database.client;
data.database_type = config.database.client;
data.email_transport = mailConfig && (mailConfig.options && mailConfig.options.service ? mailConfig.options.service : mailConfig.transport);
return when.settle(ops).then(function (descriptors) {
@ -81,7 +81,7 @@ function updateCheckData() {
posts = descriptors[3].value,
users = descriptors[4].value,
npm = descriptors[5].value,
blogUrl = url.parse(config().url),
blogUrl = url.parse(config.url),
blogId = blogUrl.hostname + blogUrl.pathname.replace(/\//, '') + hash.value;
data.blog_id = crypto.createHash('md5').update(blogId).digest('hex');
@ -175,7 +175,7 @@ function updateCheck() {
// 1. updateCheck is defined as false in config.js
// 2. we've already done a check this session
// 3. we're not in production or development mode
if (config().updateCheck === false || _.indexOf(allowedCheckEnvironments, process.env.NODE_ENV) === -1) {
if (config.updateCheck === false || _.indexOf(allowedCheckEnvironments, process.env.NODE_ENV) === -1) {
// No update check
deferred.resolve();
} else {

View File

@ -10,7 +10,7 @@ I18n = function (ghost) {
// TODO: validate
var lang = ghost.settings('defaultLang'),
path = config().paths.lang,
path = config.paths.lang,
langFilePath = path + lang + '.json';
return function (req, res, next) {

View File

@ -14,6 +14,7 @@ var _ = require('lodash'),
describe('Themes API', function () {
var configStub,
config,
sandbox,
settingsReadStub;
@ -42,7 +43,7 @@ describe('Themes API', function () {
return when({ settings: [{value: 'casper'}] });
});
configStub = sandbox.stub().returns({
configStub = {
'paths': {
'subdir': '',
'availableThemes': {
@ -54,7 +55,10 @@ describe('Themes API', function () {
}
}
}
});
};
config = ThemeAPI.__get__('config');
_.extend(config, configStub);
done();
}).catch(done);
@ -63,12 +67,6 @@ describe('Themes API', function () {
should.exist(ThemeAPI);
it('can browse', function (done) {
var config;
config = ThemeAPI.__get__('config');
_.extend(configStub, config);
ThemeAPI.__set__('config', configStub);
ThemeAPI.browse({context: {user: 1}}).then(function (result) {
should.exist(result);
result.themes.length.should.be.above(0);
@ -80,12 +78,6 @@ describe('Themes API', function () {
});
it('can edit', function (done) {
var config;
config = ThemeAPI.__get__('config');
_.extend(configStub, config);
ThemeAPI.__set__('config', configStub);
ThemeAPI.edit({themes: [{uuid: 'casper', active: true }]}, {context: {user: 1}}).then(function (result) {
should.exist(result);
should.exist(result.themes);

View File

@ -164,7 +164,7 @@ describe('Settings Model', function () {
describe('populating defaults from settings.json', function () {
beforeEach(function (done) {
config().database.knex('settings').truncate().then(function () {
config.database.knex('settings').truncate().then(function () {
done();
});
});

View File

@ -1,11 +1,14 @@
var should = require('should');
var when = require('when');
var rewire = require('rewire');
var packageInfo = require('../../../package');
var ghost = require('../../../core');
var permissions = require('../../server/permissions');
var testUtils = require('../utils');
var updateCheck = rewire('../../server/update-check');
/*globals describe, before, beforeEach, afterEach, after, it */
var should = require('should'),
rewire = require('rewire'),
_ = require('lodash'),
packageInfo = require('../../../package'),
ghost = require('../../../core'),
config = rewire('../../../core/server/config'),
defaultConfig = require('../../../config.example')[process.env.NODE_ENV],
permissions = require('../../server/permissions'),
testUtils = require('../utils'),
updateCheck = rewire('../../server/update-check');
describe('Update Check', function () {
var environmentsOrig;
@ -14,7 +17,9 @@ describe('Update Check', function () {
environmentsOrig = updateCheck.__get__('allowedCheckEnvironments');
updateCheck.__set__('allowedCheckEnvironments', ['development', 'production', 'testing']);
ghost().then(function () {
_.extend(config, defaultConfig);
ghost({config: config.paths.config}).then(function () {
return testUtils.clearData();
}).then(function () {
done();

View File

@ -35,7 +35,7 @@ describe('Bootstrap', function () {
// 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.__set__('configFile', path.join(config.paths.appRoot, 'config.example.js'));
bootstrap().then(function (config) {
config.url.should.equal(defaultConfig.url);
@ -49,7 +49,7 @@ describe('Bootstrap', function () {
});
it('uses the passed in config file location', function (done) {
bootstrap(path.join(config().paths.appRoot, 'config.example.js')).then(function (config) {
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);

View File

@ -1,4 +1,4 @@
/*globals describe, it, beforeEach, afterEach */
/*globals describe, it, before, beforeEach, afterEach */
/*jshint expr:true*/
var should = require('should'),
sinon = require('sinon'),
@ -71,17 +71,16 @@ describe('Config', function () {
});
describe('Index', function () {
// Make a copy of the default config file
// so we can restore it after every test.
// Using _.merge to recursively apply every property.
var defaultConfigFile = _.merge({}, config());
afterEach(function () {
configUpdate(defaultConfigFile);
// 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));
});
it('should have exactly the right keys', function () {
var pathConfig = config().paths;
var pathConfig = config.paths;
// This will fail if there are any extra keys
pathConfig.should.have.keys(
@ -107,7 +106,7 @@ describe('Config', function () {
});
it('should have the correct values for each key', function () {
var pathConfig = config().paths,
var pathConfig = config.paths,
appRoot = path.resolve(__dirname, '../../../');
pathConfig.should.have.property('appRoot', appRoot);
@ -116,28 +115,28 @@ describe('Config', function () {
it('should not return a slash for subdir', function () {
configUpdate({url: 'http://my-ghost-blog.com'});
config().paths.should.have.property('subdir', '');
config.paths.should.have.property('subdir', '');
configUpdate({url: 'http://my-ghost-blog.com/'});
config().paths.should.have.property('subdir', '');
config.paths.should.have.property('subdir', '');
});
it('should handle subdirectories properly', function () {
configUpdate({url: 'http://my-ghost-blog.com/blog'});
config().paths.should.have.property('subdir', '/blog');
config.paths.should.have.property('subdir', '/blog');
configUpdate({url: 'http://my-ghost-blog.com/blog/'});
config().paths.should.have.property('subdir', '/blog');
config.paths.should.have.property('subdir', '/blog');
configUpdate({url: 'http://my-ghost-blog.com/my/blog'});
config().paths.should.have.property('subdir', '/my/blog');
config.paths.should.have.property('subdir', '/my/blog');
configUpdate({url: 'http://my-ghost-blog.com/my/blog/'});
config().paths.should.have.property('subdir', '/my/blog');
config.paths.should.have.property('subdir', '/my/blog');
});
it('should allow specific properties to be user defined', function () {
var contentPath = path.join(config().paths.appRoot, 'otherContent', '/'),
var contentPath = path.join(config.paths.appRoot, 'otherContent', '/'),
configFile = 'configFileDanceParty.js';
configUpdate({
@ -147,16 +146,20 @@ describe('Config', function () {
}
});
config().should.have.property('config', configFile);
config().paths.should.have.property('contentPath', contentPath);
config().paths.should.have.property('themePath', contentPath + 'themes');
config().paths.should.have.property('appPath', contentPath + 'apps');
config().paths.should.have.property('imagesPath', contentPath + 'images');
config.should.have.property('config', configFile);
config.paths.should.have.property('contentPath', contentPath);
config.paths.should.have.property('themePath', contentPath + 'themes');
config.paths.should.have.property('appPath', contentPath + 'apps');
config.paths.should.have.property('imagesPath', contentPath + 'images');
});
});
describe('urlFor', function () {
before(function () {
configUpdate(_.merge({}, defaultConfig));
});
afterEach(function () {
configUpdate({url: defaultConfig.url});
});

View File

@ -215,24 +215,22 @@ describe('Error handling', function () {
before(function () {
originalConfig = errors.__get__('config');
errors.__set__('config', function () {
return {
'paths': {
'themePath': '/content/themes',
'availableThemes': {
'casper': {
'assets': null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'page.hbs': '/content/themes/casper/page.hbs',
'tag.hbs': '/content/themes/casper/tag.hbs'
},
'theme-with-error': {
'error.hbs':''
}
errors.__set__('config', {
'paths': {
'themePath': '/content/themes',
'availableThemes': {
'casper': {
'assets': null,
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs',
'page.hbs': '/content/themes/casper/page.hbs',
'tag.hbs': '/content/themes/casper/tag.hbs'
},
'theme-with-error': {
'error.hbs': ''
}
}
};
}
});
errors.updateActiveTheme('casper');
});

View File

@ -10,6 +10,7 @@ var assert = require('assert'),
// Stuff we are testing
api = require('../../server/api'),
config = rewire('../../server/config'),
frontend = rewire('../../server/controllers/frontend');
// To stop jshint complaining
@ -88,10 +89,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to home if page number is 0 with subdirectory', function () {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 0}, route: {path: '/page/:page/'}};
@ -104,10 +103,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to home if page number is 1 with subdirectory', function () {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 1}, route: {path: '/page/:page/'}};
@ -131,10 +128,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to last page if page number too big with subdirectory', function (done) {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 4}, route: {path: '/page/:page/'}};
@ -217,7 +212,7 @@ describe('Frontend Controller', function () {
}]
}));
frontend.__set__('config', sandbox.stub().returns({
frontend.__set__('config', {
'paths': {
'subdir': '',
'availableThemes': {
@ -230,7 +225,7 @@ describe('Frontend Controller', function () {
}
}
}
}));
});
});
describe('custom tag template', function () {
@ -317,10 +312,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to base tag page if page number is 0 with subdirectory', function () {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 0, slug: 'pumpkin'}};
@ -333,10 +326,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to base tag page if page number is 1 with subdirectory', function () {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 1, slug: 'pumpkin'}};
@ -360,10 +351,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to last page if page number too big with subdirectory', function (done) {
frontend.__set__('config', function() {
return {
paths: {subdir: '/blog'}
};
frontend.__set__('config', {
paths: {subdir: '/blog'}
});
var req = {params: {page: 4, slug: 'pumpkin'}};
@ -435,7 +424,7 @@ describe('Frontend Controller', function () {
}]
}));
frontend.__set__('config', sandbox.stub().returns({
frontend.__set__('config', {
'paths': {
'subdir': '',
'availableThemes': {
@ -449,7 +438,7 @@ describe('Frontend Controller', function () {
}
}
}
}));
});
});
describe('static pages', function () {
@ -895,13 +884,10 @@ describe('Frontend Controller', function () {
describe('rss redirects', function () {
var res,
apiUsersStub,
overwriteConfig = function(newConfig) {
configUpdate = config.__get__('updateConfig'),
overwriteConfig = function (newConfig) {
var existingConfig = frontend.__get__('config');
var newConfigModule = function() {
return newConfig;
};
newConfigModule.urlFor = existingConfig.urlFor;
frontend.__set__('config', newConfigModule);
configUpdate(_.extend(existingConfig, newConfig));
};
beforeEach(function () {
@ -995,6 +981,8 @@ describe('Frontend Controller', function () {
});
it('Redirects to last page if page number too big', function (done) {
overwriteConfig({paths: {subdir: ''}});
var req = {params: {page: 4}, route: {path: '/rss/:page/'}};
frontend.rss(req, res, done).then(function () {

View File

@ -6,10 +6,13 @@ var testUtils = require('../utils'),
when = require('when'),
assert = require('assert'),
_ = require('lodash'),
rewire = require('rewire'),
// Stuff we are testing
config = require('../../server/config'),
migration = require('../../server/data/migration'),
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'),
exporter = require('../../server/data/export'),
importer = require('../../server/data/import'),
@ -23,10 +26,14 @@ describe('Import', function () {
should.exist(exporter);
should.exist(importer);
var sandbox,
knex = config().database.knex;
var sandbox, knex;
beforeEach(function (done) {
var newConfig = _.extend(config, defaultConfig);
migration.__get__('config', newConfig);
configUpdate(newConfig);
knex = config.database.knex;
sandbox = sinon.sandbox.create();
// clear database... we need to initialise it manually for each test
testUtils.clearData().then(function () {

View File

@ -14,8 +14,7 @@ var should = require('should'),
fakeConfig,
fakeSettings,
fakeSendmail,
sandbox = sinon.sandbox.create(),
config;
sandbox = sinon.sandbox.create();
// Mock SMTP config
SMTP = {
@ -39,9 +38,11 @@ SENDMAIL = {
describe('Mail', function () {
var overrideConfig = function (newConfig) {
mailer.__set__('config', sandbox.stub().returns(
_.extend({}, defaultConfig, newConfig)
));
var config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig'),
existingConfig = mailer.__get__('config');
configUpdate(_.extend(existingConfig, newConfig));
};
beforeEach(function () {
@ -53,7 +54,7 @@ describe('Mail', function () {
};
fakeSendmail = '/fake/bin/sendmail';
config = sinon.stub().returns(fakeConfig);
overrideConfig(fakeConfig);
sandbox.stub(mailer, 'isWindows', function () {
return false;

View File

@ -9,7 +9,6 @@ var should = require('should'),
Polyglot = require('node-polyglot'),
api = require('../../server/api'),
hbs = require('express-hbs'),
packageInfo = require('../../../package'),
// Stuff we are testing
handlebars = hbs.handlebars,
@ -21,15 +20,14 @@ describe('Core Helpers', function () {
var sandbox,
apiStub,
configStub,
overrideConfig = function (newConfig) {
helpers.__set__('config', function() {
return newConfig;
});
var existingConfig = helpers.__get__('config');
configUpdate(_.extend(existingConfig, newConfig));
};
beforeEach(function (done) {
var adminHbs = hbs.create();
var adminHbs = hbs.create(),
existingConfig = helpers.__get__('config');
helpers = rewire('../../server/helpers');
sandbox = sinon.sandbox.create();
apiStub = sandbox.stub(api.settings, 'read', function () {
@ -38,8 +36,7 @@ describe('Core Helpers', function () {
});
});
config = helpers.__get__('config');
configStub = sandbox.stub().returns({
overrideConfig({
'paths': {
'subdir': '',
'availableThemes': {
@ -54,17 +51,16 @@ describe('Core Helpers', function () {
}
}
});
_.extend(configStub, config);
configStub.theme = sandbox.stub().returns({
existingConfig.theme = sandbox.stub().returns({
title: 'Ghost',
description: 'Just a blogging platform.',
url: 'http://testurl.com'
});
helpers.__set__('config', configStub);
helpers.loadCoreHelpers(adminHbs);
// Load template helpers in handlebars
hbs.express3({ partialsDir: [config().paths.helperTemplates] });
hbs.express3({ partialsDir: [config.paths.helperTemplates] });
hbs.cachePartials(function () {
done();
});
@ -400,7 +396,7 @@ describe('Core Helpers', function () {
describe('ghost_head Helper', function () {
// TODO: these tests should be easier to do!
var configUrl = config().url;
var configUrl = config.url;
afterEach(function () {
configUpdate({url: configUrl});
@ -625,10 +621,8 @@ describe('Core Helpers', function () {
});
it('can return a valid url with subdirectory', function () {
helpers.__set__('config', function() {
return {
paths: {'subdir': '/blog'}
};
_.extend(helpers.__get__('config'), {
paths: {'subdir': '/blog'}
});
helpers.page_url(1).should.equal('/blog/');
helpers.page_url(2).should.equal('/blog/page/2/');
@ -645,10 +639,8 @@ describe('Core Helpers', function () {
});
it('can return a valid url for tag pages with subdirectory', function () {
helpers.__set__('config', function() {
return {
paths: {'subdir': '/blog'}
};
_.extend(helpers.__get__('config'), {
paths: {'subdir': '/blog'}
});
var tagContext = {
tagSlug: 'pumpkin'
@ -671,10 +663,8 @@ describe('Core Helpers', function () {
});
it('can return a valid url with subdirectory', function () {
helpers.__set__('config', function() {
return {
paths: {'subdir': '/blog'}
};
_.extend(helpers.__get__('config'), {
paths: {'subdir': '/blog'}
});
helpers.pageUrl(1).should.equal('/blog/');
helpers.pageUrl(2).should.equal('/blog/page/2/');
@ -691,10 +681,8 @@ describe('Core Helpers', function () {
});
it('can return a valid url for tag pages with subdirectory', function () {
helpers.__set__('config', function() {
return {
paths: {'subdir': '/blog'}
};
_.extend(helpers.__get__('config'), {
paths: {'subdir': '/blog'}
});
var tagContext = {
tagSlug: 'pumpkin'
@ -1430,7 +1418,7 @@ describe('Core Helpers', function () {
describe('adminUrl', function () {
var rendered,
configUrl = config().url;
configUrl = config.url;
afterEach(function () {
configUpdate({url: configUrl});
@ -1519,19 +1507,15 @@ describe('Core Helpers', function () {
fileStorage.should.equal('true');
});
it('should return the config().fileStorage value when it exists', function () {
it('should return the config.fileStorage value when it exists', function () {
var setting = 'file storage value',
cfg = helpers.__get__('config'),
fileStorage;
configStub = sandbox.stub().returns({
_.extend(cfg, {
fileStorage: setting
});
_.extend(cfg, configStub);
helpers.__set__('config', cfg);
fileStorage = helpers.file_storage();
should.exist(fileStorage);
@ -1552,19 +1536,15 @@ describe('Core Helpers', function () {
apps.should.equal('false');
});
it('should return the config().apps value when it exists', function () {
it('should return the config.apps value when it exists', function () {
var setting = 'app value',
cfg = helpers.__get__('config'),
apps;
configStub = sandbox.stub().returns({
_.extend(cfg, {
apps: setting
});
_.extend(cfg, configStub);
helpers.__set__('config', cfg);
apps = helpers.apps();
should.exist(apps);

View File

@ -3,18 +3,29 @@
var fs = require('fs-extra'),
path = require('path'),
should = require('should'),
config = require('../../server/config'),
sinon = require('sinon'),
localfilesystem = require('../../server/storage/localfilesystem');
rewire = require('rewire'),
_ = require('lodash'),
config = rewire('../../server/config'),
configUpdate = config.__get__('updateConfig'),
localfilesystem = rewire('../../server/storage/localfilesystem');
// To stop jshint complaining
should.equal(true, true);
describe('Local File System Storage', function () {
var image;
var image,
overrideConfig = function (newConfig) {
var existingConfig = localfilesystem.__get__('config'),
updatedConfig = _.extend(existingConfig, newConfig);
configUpdate(updatedConfig);
localfilesystem.__set__('config', updatedConfig);
};
beforeEach(function () {
overrideConfig(config);
sinon.stub(fs, 'mkdirs').yields();
sinon.stub(fs, 'copy').yields();
sinon.stub(fs, 'exists').yields(false);
@ -121,17 +132,17 @@ describe('Local File System Storage', function () {
});
describe('when a custom content path is used', function () {
var origContentPath = config().paths.contentPath;
var origImagesPath = config().paths.imagesPath;
var origContentPath = config.paths.contentPath;
var origImagesPath = config.paths.imagesPath;
beforeEach(function () {
config().paths.contentPath = config().paths.appRoot + '/var/ghostcms';
config().paths.imagesPath = config().paths.appRoot + '/var/ghostcms/' + config().paths.imagesRelPath;
config.paths.contentPath = config.paths.appRoot + '/var/ghostcms';
config.paths.imagesPath = config.paths.appRoot + '/var/ghostcms/' + config.paths.imagesRelPath;
});
afterEach(function () {
config().paths.contentPath = origContentPath;
config().paths.imagesPath = origImagesPath;
config.paths.contentPath = origContentPath;
config.paths.imagesPath = origImagesPath;
});
it('should send the correct path to image', function (done) {

View File

@ -36,8 +36,8 @@ function findFreePort(port) {
// passing to forkGhost() method
function forkConfig() {
// require caches values, and we want to read it fresh from the file
delete require.cache[config().paths.config];
return _.cloneDeep(require(config().paths.config)[process.env.NODE_ENV]);
delete require.cache[config.paths.config];
return _.cloneDeep(require(config.paths.config)[process.env.NODE_ENV]);
}
// Creates a new fork of Ghost process with a given config
@ -51,7 +51,7 @@ function forkGhost(newConfig, envName) {
newConfig.server.port = port;
newConfig.url = url.format(_.extend(url.parse(newConfig.url), {port: port, host: null}));
var newConfigFile = path.join(config().paths.appRoot, 'config.test' + port + '.js');
var newConfigFile = path.join(config.paths.appRoot, 'config.test' + port + '.js');
fs.writeFile(newConfigFile, 'module.exports = {' + envName + ': ' + JSON.stringify(newConfig) + '}', function(err) {
if (err) throw err;
@ -59,7 +59,7 @@ function forkGhost(newConfig, envName) {
var env = _.clone(process.env);
env['GHOST_CONFIG'] = newConfigFile;
env['NODE_ENV'] = envName;
var child = cp.fork(path.join(config().paths.appRoot, 'index.js'), {env: env});
var child = cp.fork(path.join(config.paths.appRoot, 'index.js'), {env: env});
var pingTries = 0;
var pingCheck;

View File

@ -1,5 +1,4 @@
var knex = require('../../server/models/base').knex,
when = require('when'),
var when = require('when'),
sequence = require('when/sequence'),
nodefn = require('when/node'),
_ = require('lodash'),
@ -9,6 +8,7 @@ var knex = require('../../server/models/base').knex,
DataGenerator = require('./fixtures/data-generator'),
API = require('./api'),
fork = require('./fork'),
config = require('../../server/config'),
teardown;
@ -22,6 +22,7 @@ function clearData() {
}
function insertPosts() {
var knex = config.database.knex;
// ToDo: Get rid of pyramid of doom
return when(knex('posts').insert(DataGenerator.forKnex.posts).then(function () {
return knex('tags').insert(DataGenerator.forKnex.tags).then(function () {
@ -34,7 +35,8 @@ function insertMorePosts(max) {
var lang,
status,
posts = [],
i, j, k = 0;
i, j, k = 0,
knex = config.database.knex;
max = max || 50;
@ -57,6 +59,7 @@ function insertMorePosts(max) {
function insertMorePostsTags(max) {
max = max || 50;
var knex = config.database.knex;
return when.all([
// PostgreSQL can return results in any order
@ -79,8 +82,8 @@ function insertMorePostsTags(max) {
promises.push(DataGenerator.forKnex.createPostsTags(posts[i], injectionTagId));
}
return sequence(_.times(promises.length, function(index) {
return function() {
return sequence(_.times(promises.length, function (index) {
return function () {
return knex('posts_tags').insert(promises[index]);
};
}));
@ -88,7 +91,8 @@ function insertMorePostsTags(max) {
}
function insertDefaultUser() {
var user;
var user,
knex = config.database.knex;
user = DataGenerator.forKnex.createUser(DataGenerator.Content.users[0]);
@ -99,7 +103,8 @@ function insertDefaultUser() {
function insertAdminUser() {
var users = [],
userRoles = [];
userRoles = [],
knex = config.database.knex;
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[1]));
userRoles.push(DataGenerator.forKnex.createUserRole(2, 2));
@ -112,7 +117,8 @@ function insertAdminUser() {
function insertEditorUser() {
var users = [],
userRoles = [];
userRoles = [],
knex = config.database.knex;
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[2]));
userRoles.push(DataGenerator.forKnex.createUserRole(3, 2));
@ -125,7 +131,8 @@ function insertEditorUser() {
function insertAuthorUser() {
var users = [],
userRoles = [];
userRoles = [],
knex = config.database.knex;
users.push(DataGenerator.forKnex.createUser(DataGenerator.Content.users[3]));
userRoles.push(DataGenerator.forKnex.createUserRole(4, 3));
@ -137,7 +144,8 @@ function insertAuthorUser() {
}
function insertDefaultApp() {
var apps = [];
var apps = [],
knex = config.database.knex;
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
@ -164,13 +172,16 @@ function insertDefaultApp() {
}
function insertApps() {
var knex = config.database.knex;
return knex('apps').insert(DataGenerator.forKnex.apps).then(function () {
return knex('app_fields').insert(DataGenerator.forKnex.app_fields);
});
}
function insertAppWithSettings() {
var apps = [], app_settings = [];
var apps = [],
app_settings = [],
knex = config.database.knex;
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
app_settings.push(DataGenerator.forKnex.createAppSetting(DataGenerator.Content.app_settings[0]));
@ -178,9 +189,9 @@ function insertAppWithSettings() {
return knex('apps').insert(apps, 'id')
.then(function (results) {
var appId = results[0];
var appId = results[0], i;
for (var i = 0; i < app_settings.length; i++) {
for (i = 0; i < app_settings.length; i++) {
app_settings[i].app_id = appId;
}
@ -188,7 +199,9 @@ function insertAppWithSettings() {
});
}
function insertAppWithFields() {
var apps = [], app_fields = [];
var apps = [],
app_fields = [],
knex = config.database.knex;
apps.push(DataGenerator.forKnex.createApp(DataGenerator.Content.apps[0]));
app_fields.push(DataGenerator.forKnex.createAppField(DataGenerator.Content.app_fields[0]));