0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

🔥 do not store settings in config (#7924)

* 🎨  🔥  do not store settings in config and make settings cache easier available

- remove remembering settings value in theme config
- if we need a cache value, we are asking the settings cache directly
- instead of settings.getSettingSync we use settings.cache.get

- added TODO:
  - think about moving the settings cache out of api/settings
  - we could create a folder named cache cache/settings
  - this settings cache listens on model changes for settings
  - decoupling

* 🔥  remove timezone from config

- no need to store in overrides config and in defaults settings

* 🎨  context object helper

- replace config.get('theme') by settings cache

* 🎨  replace config.get('theme') by settings.cache.get

* 🎨  adapt tests

* fixes from comments
This commit is contained in:
Katharina Irrgang 2017-02-03 14:15:11 +01:00 committed by Hannah Wolfe
parent 16f5d1fdaf
commit 0201c431d7
39 changed files with 493 additions and 486 deletions

View file

@ -2,6 +2,7 @@
// RESTful API for browsing the configuration
var _ = require('lodash'),
config = require('../config'),
settingsCache = require('../api/settings').cache,
ghostVersion = require('../utils/ghost-version'),
models = require('../models'),
Promise = require('bluebird'),
@ -29,7 +30,7 @@ function getBaseConfig() {
useGravatar: !config.isPrivacyDisabled('useGravatar'),
publicAPI: config.get('publicAPI') === true,
blogUrl: utils.url.urlFor('home', true),
blogTitle: config.get('theme').title,
blogTitle: settingsCache.get('title'),
routeKeywords: config.get('routeKeywords')
};
}

View file

@ -6,15 +6,12 @@ var _ = require('lodash'),
config = require('../config'),
canThis = require('../permissions').canThis,
errors = require('../errors'),
logging = require('../logging'),
utils = require('./utils'),
i18n = require('../i18n'),
globalUtils = require('../utils'),
docName = 'settings',
settings,
updateConfigCache,
updateSettingsCache,
settingsFilter,
filterPaths,
@ -31,49 +28,6 @@ var _ = require('lodash'),
*/
settingsCache = {};
/**
* ### Updates Config Theme Settings
* Maintains the cache of theme specific variables that are reliant on settings.
* @private
*/
updateConfigCache = function () {
var labsValue = {};
if (settingsCache.labs && settingsCache.labs.value) {
try {
labsValue = JSON.parse(settingsCache.labs.value);
} catch (err) {
logging.error(new errors.GhostError({
err: err,
message: i18n.t('errors.api.settings.invalidJsonInLabs'),
context: i18n.t('errors.api.settings.labsColumnCouldNotBeParsed'),
help: i18n.t('errors.api.settings.tryUpdatingLabs')
}));
}
}
// @TODO: why are we putting the settings cache values into config?we could access the cache directly
// @TODO: plus: why do we assign the values to the prefix "theme"?
// @TODO: might be related to https://github.com/TryGhost/Ghost/issues/7488
config.set('theme:title', (settingsCache.title && settingsCache.title.value) || '');
config.set('theme:description', (settingsCache.description && settingsCache.description.value) || '');
config.set('theme:logo', (settingsCache.logo && settingsCache.logo.value) || '');
config.set('theme:cover', (settingsCache.cover && settingsCache.cover.value) || '');
config.set('theme:navigation', (settingsCache.navigation && JSON.parse(settingsCache.navigation.value)) || []);
config.set('theme:postsPerPage', (settingsCache.postsPerPage && settingsCache.postsPerPage.value) || config.get('theme').postsPerPage);
config.set('theme:permalinks', (settingsCache.permalinks && settingsCache.permalinks.value) || config.get('theme').permalinks);
config.set('theme:twitter', (settingsCache.twitter && settingsCache.twitter.value) || '');
config.set('theme:facebook', (settingsCache.facebook && settingsCache.facebook.value) || '');
config.set('theme:timezone', (settingsCache.activeTimezone && settingsCache.activeTimezone.value) || config.get('theme').timezone);
config.set('theme:url', globalUtils.url.urlFor('home', true));
config.set('theme:amp', (settingsCache.amp && settingsCache.amp.value === 'true'));
config.set('theme:icon', settingsCache.icon && settingsCache.icon.value);
_.each(labsValue, function (value, key) {
config.set('labs:' + key, value);
});
};
/**
* ### Update Settings Cache
* Maintain the internal cache of the settings object
@ -90,8 +44,6 @@ updateSettingsCache = function (settings, options) {
settingsCache[key] = setting;
});
updateConfigCache();
return Promise.resolve(settingsCache);
}
@ -99,7 +51,7 @@ updateSettingsCache = function (settings, options) {
.then(function (result) {
// keep reference and update all keys
_.extend(settingsCache, readSettingsResult(result.models));
updateConfigCache();
return settingsCache;
});
};
@ -187,6 +139,7 @@ readSettingsResult = function (settingsModels) {
apps = config.get('paths').availableApps,
res;
// @TODO: remove availableThemes from settings cache and create an endpoint to fetch themes
if (settings.activeTheme && themes) {
res = filterPaths(themes, settings.activeTheme.value);
@ -255,7 +208,7 @@ populateDefaultSetting = function (key) {
return Promise.reject(err);
}
// TODO: Different kind of error?
// TODO: different kind of error?
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.settings.problemFindingSetting', {key: key})}));
});
};
@ -434,19 +387,36 @@ settings = {
module.exports = settings;
/**
* synchronous function to get cached settings value
* returns the value of the settings entry
* @TODO:
* - move settings cache somewhere else e.q. listen on model changes
*
* IMPORTANT:
* We store settings with a type and a key in the database.
*
* {
* type: core
* key: dbHash
* value: ...
* }
*
* But the settings cache does not allow requesting a value by type, only by key.
* e.g. settings.cache.get('dbHash')
*/
module.exports.getSettingSync = function getSettingSync(key) {
return settingsCache[key] && settingsCache[key].value;
};
module.exports.cache = {
get: function get(key) {
if (!settingsCache[key]) {
return;
}
/**
* synchronous function to get all cached settings values
* returns everything for now
*/
module.exports.getSettingsSync = function getSettingsSync() {
return settingsCache;
try {
return JSON.parse(settingsCache[key].value);
} catch (err) {
return settingsCache[key].value;
}
},
getAll: function getAll() {
return settingsCache;
}
};
module.exports.updateSettingsCache = updateSettingsCache;

View file

@ -5,8 +5,8 @@ var path = require('path'),
i18n = require('../../../i18n'),
// Dirty requires
config = require('../../../config'),
errors = require('../../../errors'),
settingsCache = require('../../../api/settings').cache,
templates = require('../../../controllers/frontend/templates'),
postLookup = require('../../../controllers/frontend/post-lookup'),
setResponseContext = require('../../../controllers/frontend/context');
@ -36,6 +36,7 @@ function controller(req, res, next) {
function getPostData(req, res, next) {
req.body = req.body || {};
postLookup(res.locals.relativeUrl)
.then(function (result) {
if (result && result.post) {
@ -50,7 +51,7 @@ function getPostData(req, res, next) {
}
function checkIfAMPIsEnabled(req, res, next) {
var ampIsEnabled = config.get('theme:amp');
var ampIsEnabled = settingsCache.get('amp');
if (ampIsEnabled) {
return next();

View file

@ -63,9 +63,6 @@
"cannotScheduleAPostBeforeInMinutes": 2,
"publishAPostBySchedulerToleranceInMinutes": 2
},
"theme": {
"timezone": "Etc/UTC"
},
"maintenance": {
"enabled": false
}

View file

@ -4,8 +4,8 @@
*/
var api = require('../../api'),
_ = require('lodash'),
config = require('../../config'),
Promise = require('bluebird'),
settingsCache = api.settings.cache,
queryDefaults,
defaultPostQuery = {};
@ -33,7 +33,7 @@ _.extend(defaultPostQuery, queryDefaults, {
function fetchPostsPerPage(options) {
options = options || {};
var postsPerPage = parseInt(config.get('theme').postsPerPage);
var postsPerPage = parseInt(settingsCache.get('postsPerPage'));
// No negative posts per page, must be number
if (!isNaN(postsPerPage) && postsPerPage > 0) {

View file

@ -3,8 +3,7 @@ var _ = require('lodash'),
url = require('url'),
routeMatch = require('path-match')(),
api = require('../../api'),
config = require('../../config'),
settingsCache = api.settings.cache,
optionsFormat = '/:options?';
function getOptionsFormat(linkStructure) {
@ -13,7 +12,7 @@ function getOptionsFormat(linkStructure) {
function postLookup(postUrl) {
var postPath = url.parse(postUrl).path,
postPermalink = config.get('theme').permalinks,
postPermalink = settingsCache.get('permalinks'),
pagePermalink = '/:slug/',
isEditURL = false,
matchFuncPost,

View file

@ -1,4 +1,5 @@
var config = require('../../config'),
settingsCache = require('../../api/settings').cache,
utils = require('../../utils');
function getAssetUrl(path, isAdmin, minify) {
@ -19,7 +20,11 @@ function getAssetUrl(path, isAdmin, minify) {
if (isAdmin) {
output = utils.url.urlJoin(utils.url.getSubdir(), '/favicon.ico');
} else {
output = config.get('theme:icon') ? utils.url.urlJoin(utils.url.getSubdir(), utils.url.urlFor('image', {image: config.get('theme:icon')})) : utils.url.urlJoin(utils.url.getSubdir(), '/favicon.ico');
if (settingsCache.get('icon')) {
output = utils.url.urlJoin(utils.url.getSubdir(), utils.url.urlFor('image', {image: settingsCache.get('icon')}));
} else {
output = utils.url.urlJoin(utils.url.getSubdir(), '/favicon.ico');
}
}
}
// Get rid of any leading slash on the path

View file

@ -1,8 +1,15 @@
var config = require('../../config'),
_ = require('lodash');
var settingsCache = require('../../api/settings').cache,
_ = require('lodash');
function getContextObject(data, context) {
var blog = config.get('theme'),
/**
* If the data object does not contain the requested context, we return the fallback object.
*/
var blog = {
cover: settingsCache.get('cover'),
twitter: settingsCache.get('twitter'),
facebook: settingsCache.get('facebook')
},
contextObject;
context = _.includes(context, 'page') || _.includes(context, 'amp') ? 'post' : context;

View file

@ -1,16 +1,17 @@
var _ = require('lodash'),
config = require('../../config');
settingsCache = require('../../api/settings').cache;
function getDescription(data, root) {
var description = '',
context = root ? root.context : null;
context = root ? root.context : null,
blogDescription = settingsCache.get('description');
if (data.meta_description) {
description = data.meta_description;
} else if (_.includes(context, 'paged')) {
description = '';
} else if (_.includes(context, 'home')) {
description = config.get('theme').description;
description = blogDescription;
} else if (_.includes(context, 'author') && data.author) {
description = data.author.meta_description || data.author.bio;
} else if (_.includes(context, 'tag') && data.tag) {

View file

@ -1,6 +1,5 @@
var _ = require('lodash'),
Promise = require('bluebird'),
config = require('../../config'),
var Promise = require('bluebird'),
settingsCache = require('../../api/settings').cache,
utils = require('../../utils'),
getUrl = require('./url'),
getImageDimensions = require('./image-dimensions'),
@ -46,12 +45,30 @@ function getMetaData(data, root) {
publishedDate: getPublishedDate(data),
modifiedDate: getModifiedDate(data),
ogType: getOgType(data),
blog: _.cloneDeep(config.get('theme'))
// @TODO: pass into each meta helper - wrap each helper
blog: {
title: settingsCache.get('title'),
description: settingsCache.get('description'),
url: utils.url.urlFor('home', true),
facebook: settingsCache.get('facebook'),
twitter: settingsCache.get('twitter'),
timezone: settingsCache.get('activeTimezone'),
navigation: settingsCache.get('navigation'),
posts_per_page: settingsCache.get('postsPerPage'),
icon: settingsCache.get('icon'),
cover: settingsCache.get('cover'),
logo: settingsCache.get('logo'),
amp: settingsCache.get('amp')
}
};
metaData.blog.logo = {};
metaData.blog.logo.url = config.get('theme').logo ?
utils.url.urlFor('image', {image: config.get('theme').logo}, true) : utils.url.urlJoin(utils.url.urlFor('admin'), 'img/ghosticon.jpg');
if (settingsCache.get('logo')) {
metaData.blog.logo.url = utils.url.urlFor('image', {image: settingsCache.get('logo')}, true);
} else {
metaData.blog.logo.url = utils.url.urlJoin(utils.url.urlFor('admin'), 'img/ghosticon.jpg');
}
// TODO: cleanup these if statements
if (data.post && data.post.html) {

View file

@ -1,28 +1,29 @@
var _ = require('lodash'),
config = require('../../config');
settingsCache = require('../../api/settings').cache;
function getTitle(data, root) {
var title = '',
context = root ? root.context : null,
blog = config.get('theme'),
blogTitle = settingsCache.get('title'),
pagination = root ? root.pagination : null,
pageString = '';
if (pagination && pagination.total > 1) {
pageString = ' - Page ' + pagination.page;
}
if (data.meta_title) {
title = data.meta_title;
} else if (_.includes(context, 'home')) {
title = blog.title;
title = blogTitle;
} else if (_.includes(context, 'author') && data.author) {
title = data.author.name + pageString + ' - ' + blog.title;
title = data.author.name + pageString + ' - ' + blogTitle;
} else if (_.includes(context, 'tag') && data.tag) {
title = data.tag.meta_title || data.tag.name + pageString + ' - ' + blog.title;
title = data.tag.meta_title || data.tag.name + pageString + ' - ' + blogTitle;
} else if ((_.includes(context, 'post') || _.includes(context, 'page')) && data.post) {
title = data.post.meta_title || data.post.title;
} else {
title = blog.title + pageString;
title = blogTitle + pageString;
}
return (title || '').trim();

View file

@ -7,6 +7,7 @@ var crypto = require('crypto'),
i18n = require('../../../i18n'),
filters = require('../../../filters'),
processUrls = require('../../../utils/make-absolute-urls'),
settingsCache = require('../../../api/settings').cache,
// Really ugly temporary hack for location of things
fetchData = require('../../../controllers/frontend/fetch-data'),
@ -41,8 +42,8 @@ function getData(channelOpts, slugParam) {
if (result.data && result.data.tag) { titleStart = result.data.tag[0].name + ' - ' || ''; }
if (result.data && result.data.author) { titleStart = result.data.author[0].name + ' - ' || ''; }
response.title = titleStart + config.get('theme').title;
response.description = config.get('theme').description;
response.title = titleStart + settingsCache.get('title');
response.description = settingsCache.get('description');
response.results = {
posts: result.posts,
meta: result.meta

View file

@ -17,18 +17,21 @@ var getMetaData = require('../data/meta'),
Promise = require('bluebird'),
labs = require('../utils/labs'),
utils = require('../utils'),
api = require('../api');
api = require('../api'),
settingsCache = api.settings.cache;
function getClient() {
if (labs.isSet('publicAPI') === true) {
return api.clients.read({slug: 'ghost-frontend'}).then(function (client) {
client = client.clients[0];
if (client.status === 'enabled') {
return {
id: client.slug,
secret: client.secret
};
}
return {};
});
}
@ -42,6 +45,7 @@ function writeMetaTag(property, content, type) {
function finaliseStructuredData(metaData) {
var head = [];
_.each(metaData.structuredData, function (content, property) {
if (property === 'article:tag') {
_.each(metaData.keywords, function (keyword) {
@ -57,6 +61,7 @@ function finaliseStructuredData(metaData) {
escapeExpression(content)));
}
});
return head;
}
@ -88,9 +93,10 @@ function ghost_head(options) {
metaData: getMetaData(this, options.data.root),
client: getClient()
},
blogIcon = settingsCache.get('icon'),
// CASE: blog icon is not set in config, we serve the default
iconType = !config.get('theme:icon') ? 'x-icon' : config.get('theme:icon').match(/\/favicon\.ico$/i) ? 'x-icon' : 'png',
favicon = !config.get('theme:icon') ? '/favicon.ico' : utils.url.urlFor('image', {image: config.get('theme:icon')});
iconType = !blogIcon ? 'x-icon' : blogIcon.match(/\/favicon\.ico$/i) ? 'x-icon' : 'png',
favicon = !blogIcon ? '/favicon.ico' : utils.url.urlFor('image', {image: blogIcon});
return Promise.props(fetch).then(function (response) {
client = response.client;
@ -104,7 +110,7 @@ function ghost_head(options) {
head.push('<meta name="referrer" content="' + referrerPolicy + '" />');
// show amp link in post when 1. we are not on the amp page and 2. amp is enabled
if (_.includes(context, 'post') && !_.includes(context, 'amp') && config.get('theme:amp')) {
if (_.includes(context, 'post') && !_.includes(context, 'amp') && settingsCache.get('amp')) {
head.push('<link rel="amphtml" href="' +
escapeExpression(metaData.ampUrl) + '" />');
}
@ -138,6 +144,7 @@ function ghost_head(options) {
head.push('<meta name="generator" content="Ghost ' +
escapeExpression(safeVersion) + '" />');
head.push('<link rel="alternate" type="application/rss+xml" title="' +
escapeExpression(metaData.blog.title) + '" href="' +
escapeExpression(metaData.rssUrl) + '" />');

View file

@ -151,8 +151,8 @@ function init(options) {
ghostAuthUrl: config.get('auth:url'),
redirectUri: utils.url.urlFor('admin', true),
clientUri: utils.url.urlFor('home', true),
clientName: api.settings.getSettingSync('title'),
clientDescription: api.settings.getSettingSync('description')
clientName: api.settings.cache.get('title'),
clientDescription: api.settings.cache.get('description')
}).then(function (response) {
parentApp.use(response.auth);
}).catch(function onAuthError(err) {

View file

@ -5,6 +5,7 @@ var _ = require('lodash'),
nodemailer = require('nodemailer'),
validator = require('validator'),
config = require('../config'),
settingsCache = require('../api/settings').cache,
i18n = require('../i18n'),
utils = require('../utils');
@ -31,8 +32,7 @@ GhostMailer.prototype.from = function () {
// If we do have a from address, and it's just an email
if (validator.isEmail(from)) {
defaultBlogTitle = config.get('theme').title ? config.get('theme').title : i18n.t('common.mail.title', {domain: this.getDomain()});
defaultBlogTitle = settingsCache.get('title') || i18n.t('common.mail.title', {domain: this.getDomain()});
from = '"' + defaultBlogTitle + '" <' + from + '>';
}

View file

@ -1,7 +1,7 @@
var fs = require('fs'),
path = require('path'),
storage = require('../storage'),
config = require('../config'),
settingsCache = require('../api/settings').cache,
utils = require('../utils'),
crypto = require('crypto'),
buildContentResponse,
@ -35,13 +35,13 @@ function serveFavicon() {
// we are using an express route to skip /content/images and the result is a image path
// based on config.getContentPath('images') + req.path
// in this case we don't use path rewrite, that's why we have to make it manually
filePath = config.get('theme:icon').replace(/\/content\/images\//, '');
filePath = settingsCache.get('icon').replace(/\/content\/images\//, '');
var originalExtension = path.extname(filePath).toLowerCase(),
requestedExtension = path.extname(req.path).toLowerCase();
// CASE: custom favicon exists, load it from local file storage
if (config.get('theme:icon')) {
if (settingsCache.get('icon')) {
// depends on the uploaded icon extension
if (originalExtension !== requestedExtension) {
return res.redirect(302, '/favicon' + originalExtension);
@ -52,8 +52,7 @@ function serveFavicon() {
return next(err);
}
iconType = config.get('theme:icon').match(/\/favicon\.ico$/i) ? 'x-icon' : 'png';
iconType = settingsCache.get('icon').match(/\/favicon\.ico$/i) ? 'x-icon' : 'png';
content = buildContentResponse(iconType, buf);
res.writeHead(200, content.headers);

View file

@ -3,7 +3,9 @@ var _ = require('lodash'),
path = require('path'),
hbs = require('express-hbs'),
api = require('../api'),
settingsCache = api.settings.cache,
config = require('../config'),
utils = require('../utils'),
logging = require('../logging'),
errors = require('../errors'),
i18n = require('../i18n'),
@ -13,8 +15,21 @@ themeHandler = {
// ### configHbsForContext Middleware
// Setup handlebars for the current context (admin or theme)
configHbsForContext: function configHbsForContext(req, res, next) {
var themeData = _.cloneDeep(config.get('theme')),
labsData = _.cloneDeep(config.get('labs')),
var themeData = {
title: settingsCache.get('title'),
description: settingsCache.get('description'),
url: utils.url.urlFor('home', true),
facebook: settingsCache.get('facebook'),
twitter: settingsCache.get('twitter'),
timezone: settingsCache.get('activeTimezone'),
navigation: settingsCache.get('navigation'),
posts_per_page: settingsCache.get('postsPerPage'),
icon: settingsCache.get('icon'),
cover: settingsCache.get('cover'),
logo: settingsCache.get('logo'),
amp: settingsCache.get('amp')
},
labsData = _.cloneDeep(settingsCache.get('labs')),
blogApp = req.app;
if (req.secure && config.get('urlSSL')) {
@ -22,11 +37,12 @@ themeHandler = {
themeData.url = config.get('urlSSL').replace(/\/$/, '');
}
// Change camelCase to snake_case
themeData.posts_per_page = themeData.postsPerPage;
delete themeData.postsPerPage;
hbs.updateTemplateOptions({data: {blog: themeData, labs: labsData}});
hbs.updateTemplateOptions({
data: {
blog: themeData,
labs: labsData
}
});
if (config.getContentPath('themes') && blogApp.get('activeTheme')) {
blogApp.set('views', path.join(config.getContentPath('themes'), blogApp.get('activeTheme')));

View file

@ -1,9 +1,8 @@
var config = require('../config'),
var settingsCache = require('../api/settings').cache,
flagIsSet;
flagIsSet = function flagIsSet(flag) {
var labsConfig = config.get('labs');
var labsConfig = settingsCache.get('labs');
return labsConfig && labsConfig[flag] && labsConfig[flag] === true;
};

View file

@ -5,6 +5,7 @@ var moment = require('moment-timezone'),
_ = require('lodash'),
url = require('url'),
config = require('./../config'),
settingsCache = require('./../api/settings').cache,
// @TODO: unify this with routes.apiBaseUrl
apiPath = '/ghost/api/v0.1';
@ -146,8 +147,8 @@ function createUrl(urlPath, absolute, secure) {
*/
function urlPathForPost(post) {
var output = '',
permalinks = config.get('theme').permalinks,
publishedAtMoment = moment.tz(post.published_at || Date.now(), config.get('theme').timezone),
permalinks = settingsCache.get('permalinks'),
publishedAtMoment = moment.tz(post.published_at || Date.now(), settingsCache.get('activeTimezone')),
tags = {
year: function () { return publishedAtMoment.format('YYYY'); },
month: function () { return publishedAtMoment.format('MM'); },

View file

@ -6,10 +6,12 @@
var request = require('supertest'),
should = require('should'),
moment = require('moment'),
sinon = require('sinon'),
cheerio = require('cheerio'),
testUtils = require('../../utils'),
configUtils = require('../../utils/configUtils'),
ghost = testUtils.startGhost;
settingsCache = require('../../../server/api/settings').cache,
sandbox = sinon.sandbox.create(),
ghost = testUtils.startGhost;
describe('Frontend Routing', function () {
function doEnd(done) {
@ -48,6 +50,10 @@ describe('Frontend Routing', function () {
});
});
afterEach(function () {
sandbox.restore();
});
describe('Date permalinks', function () {
before(function (done) {
// Only way to swap permalinks setting is to login and visit the URL because
@ -312,16 +318,20 @@ describe('Frontend Routing', function () {
});
it('should not render AMP, when AMP is disabled', function (done) {
after(function () {
configUtils.restore();
var originalFn = settingsCache.get;
sandbox.stub(settingsCache, 'get', function (key) {
if (key !== 'amp') {
return originalFn(key);
}
return false;
});
configUtils.set('theme:amp', false);
request.get('/welcome-to-ghost/amp/')
.expect(404)
.expect(/Page not found/)
.end(doEnd(done));
.expect(404)
.expect(/Page not found/)
.end(doEnd(done));
});
});
@ -550,11 +560,16 @@ describe('Frontend Routing', function () {
});
it('/blog/welcome-to-ghost/amp/ should 200', function (done) {
after(function () {
configUtils.restore();
var originalFn = settingsCache.get;
sandbox.stub(settingsCache, 'get', function (key) {
if (key !== 'amp') {
return originalFn(key);
}
return true;
});
configUtils.set('theme:amp', true);
request.get('/blog/welcome-to-ghost/amp/')
.expect(200)
.end(doEnd(done));
@ -637,11 +652,16 @@ describe('Frontend Routing', function () {
});
it('/blog/welcome-to-ghost/amp/ should 200', function (done) {
after(function () {
configUtils.restore();
var originalFn = settingsCache.get;
sandbox.stub(settingsCache, 'get', function (key) {
if (key !== 'amp') {
return originalFn(key);
}
return true;
});
configUtils.set('theme:amp', true);
request.get('/blog/welcome-to-ghost/amp/')
.expect(200)
.end(doEnd(done));

View file

@ -1,5 +1,6 @@
var Promise = require('bluebird'),
should = require('should'),
sinon = require('sinon'),
_ = require('lodash'),
ObjectId = require('bson-objectid'),
testUtils = require('../../utils'),
@ -7,9 +8,13 @@ var Promise = require('bluebird'),
errors = require('../../../server/errors'),
db = require('../../../server/data/db'),
models = require('../../../server/models'),
PostAPI = require('../../../server/api/posts');
PostAPI = require('../../../server/api/posts'),
settingsCache = require('../../../server/api/settings').cache,
sandbox = sinon.sandbox.create();
describe('Post API', function () {
var localSettingsCache = {};
before(testUtils.teardown);
afterEach(testUtils.teardown);
beforeEach(testUtils.setup('users:roles', 'perms:post', 'perms:init'));
@ -40,11 +45,22 @@ describe('Post API', function () {
.catch(done);
});
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
afterEach(function () {
sandbox.restore();
localSettingsCache = {};
});
should.exist(PostAPI);
describe('Browse', function () {
beforeEach(function () {
configUtils.set('theme:permalinks', '/:slug/');
localSettingsCache.permalinks = '/:slug/';
});
afterEach(function () {

View file

@ -115,10 +115,10 @@ describe('Settings API', function () {
});
it('can edit', function () {
var testReference = SettingsAPI.getSettingsSync();
var testReference = SettingsAPI.cache.getAll();
// see default-settings.json
SettingsAPI.getSettingSync('title').should.eql('Ghost');
SettingsAPI.cache.get('title').should.eql('Ghost');
testReference.title.value.should.eql('Ghost');
return callApiWithContext(defaultContext, 'edit', {settings: [{key: 'title', value: 'UpdatedGhost'}]}, {})
@ -128,7 +128,7 @@ describe('Settings API', function () {
response.settings.length.should.equal(1);
testUtils.API.checkResponse(response.settings[0], 'setting');
SettingsAPI.getSettingSync('title').should.eql('UpdatedGhost');
SettingsAPI.cache.get('title').should.eql('UpdatedGhost');
testReference.title.value.should.eql('UpdatedGhost');
});
});

View file

@ -4,17 +4,16 @@ var testUtils = require('../../utils'),
_ = require('lodash'),
Promise = require('bluebird'),
sinon = require('sinon'),
// Stuff we are testing
sequence = require('../../../server/utils/sequence'),
settingsCache = require('../../../server/api/settings').cache,
ghostBookshelf = require('../../../server/models/base'),
PostModel = require('../../../server/models/post').Post,
TagModel = require('../../../server/models/tag').Tag,
events = require('../../../server/events'),
errors = require('../../../server/errors'),
configUtils = require('../../utils/configUtils'),
DataGenerator = testUtils.DataGenerator,
context = testUtils.context.owner,
configUtils = require('../../utils/configUtils'),
sandbox = sinon.sandbox.create();
/**
@ -64,7 +63,11 @@ describe('Post Model', function () {
describe('findAll', function () {
beforeEach(function () {
configUtils.set('theme:permalinks', '/:slug/');
sandbox.stub(settingsCache, 'get', function (key) {
return {
permalinks: '/:slug/'
}[key];
});
});
it('can findAll', function (done) {
@ -94,9 +97,11 @@ describe('Post Model', function () {
describe('findPage', function () {
beforeEach(function () {
configUtils.set({theme: {
permalinks: '/:slug/'
}});
sandbox.stub(settingsCache, 'get', function (key) {
return {
permalinks: '/:slug/'
}[key];
});
});
it('can findPage (default)', function (done) {
@ -281,7 +286,11 @@ describe('Post Model', function () {
describe('findOne', function () {
beforeEach(function () {
configUtils.set('theme:permalinks', '/:slug/');
sandbox.stub(settingsCache, 'get', function (key) {
return {
permalinks: '/:slug/'
}[key];
});
});
it('can findOne', function (done) {
@ -328,7 +337,13 @@ describe('Post Model', function () {
});
it('can findOne, returning a dated permalink', function (done) {
configUtils.set('theme:permalinks', '/:year/:month/:day/:slug/');
settingsCache.get.restore();
sandbox.stub(settingsCache, 'get', function (key) {
return {
permalinks: '/:year/:month/:day/:slug/'
}[key];
});
PostModel.findOne({id: testUtils.DataGenerator.Content.posts[0].id})
.then(function (result) {
@ -347,6 +362,7 @@ describe('Post Model', function () {
describe('edit', function () {
beforeEach(function () {
eventsTriggered = {};
sandbox.stub(events, 'emit', function (eventName, eventObj) {
if (!eventsTriggered[eventName]) {
eventsTriggered[eventName] = [];
@ -827,6 +843,7 @@ describe('Post Model', function () {
describe('add', function () {
beforeEach(function () {
eventsTriggered = {};
sandbox.stub(events, 'emit', function (eventName, eventObj) {
if (!eventsTriggered[eventName]) {
eventsTriggered[eventName] = [];

View file

@ -4,14 +4,12 @@ var should = require('should'),
path = require('path'),
rewire = require('rewire'),
_ = require('lodash'),
i18n = require('../../../server/i18n'),
configUtils = require('../../utils/configUtils');
should.equal(true, true);
describe('Config', function () {
before(function () {
i18n.init();
configUtils.restore();
});
@ -84,66 +82,6 @@ describe('Config', function () {
});
});
describe('Theme', function () {
beforeEach(function () {
configUtils.set({
url: 'http://my-ghost-blog.com',
theme: {
title: 'casper',
description: 'casper',
logo: 'casper',
cover: 'casper',
timezone: 'Etc/UTC',
icon: 'core/shared/favicon.ico'
}
});
});
it('should have exactly the right keys', function () {
var themeConfig = configUtils.config.get('theme');
// This will fail if there are any extra keys
themeConfig.should.have.keys('title', 'description', 'logo', 'cover', 'timezone', 'icon');
});
it('should have the correct values for each key', function () {
var themeConfig = configUtils.config.get('theme');
// Check values are as we expect
themeConfig.should.have.property('title', 'casper');
themeConfig.should.have.property('description', 'casper');
themeConfig.should.have.property('logo', 'casper');
themeConfig.should.have.property('cover', 'casper');
themeConfig.should.have.property('timezone', 'Etc/UTC');
themeConfig.should.have.property('icon', 'core/shared/favicon.ico');
});
});
describe('Timezone default', function () {
it('should use timezone from settings when set', function () {
var themeConfig = configUtils.config.get('theme');
// Check values are as we expect
themeConfig.should.have.property('timezone', 'Etc/UTC');
configUtils.set({
theme: {
timezone: 'Africa/Cairo'
}
});
configUtils.config.get('theme').should.have.property('timezone', 'Africa/Cairo');
});
it('should set theme object with timezone by default', function () {
var themeConfig = configUtils.defaultConfig;
// Check values are as we expect
themeConfig.should.have.property('theme');
themeConfig.theme.should.have.property('timezone', 'Etc/UTC');
});
});
describe('Index', function () {
it('should have exactly the right keys', function () {
var pathConfig = configUtils.config.get('paths');

View file

@ -15,6 +15,7 @@ describe('fetchData', function () {
beforeEach(function () {
apiPostsStub = sandbox.stub(api.posts, 'browse')
.returns(new Promise.resolve({posts: [], meta: {pagination: {}}}));
apiTagStub = sandbox.stub(api.tags, 'read').returns(new Promise.resolve({tags: []}));
apiUserStub = sandbox.stub(api.users, 'read').returns(new Promise.resolve({users: []}));
});
@ -26,7 +27,7 @@ describe('fetchData', function () {
describe('channel config', function () {
beforeEach(function () {
configUtils.set({theme: {postsPerPage: 10}});
sandbox.stub(api.settings.cache, 'get').returns(10);
});
it('should handle no post options', function (done) {
@ -66,7 +67,10 @@ describe('fetchData', function () {
featured: {
type: 'browse',
resource: 'posts',
options: {filter: 'featured:true', limit: 3}
options: {
filter: 'featured:true',
limit: 3
}
}
}
};
@ -89,7 +93,9 @@ describe('fetchData', function () {
it('should handle multiple queries with page param', function (done) {
var channelOpts = {
postOptions: {page: 2},
postOptions: {
page: 2
},
data: {
featured: {
type: 'browse',
@ -148,7 +154,7 @@ describe('fetchData', function () {
describe('valid postsPerPage', function () {
beforeEach(function () {
configUtils.set({theme: {postsPerPage: 10}});
sandbox.stub(api.settings.cache, 'get').returns(10);
});
it('Adds limit & includes to options by default', function (done) {
@ -164,7 +170,7 @@ describe('fetchData', function () {
describe('invalid postsPerPage', function () {
beforeEach(function () {
configUtils.set({theme: {postsPerPage: '-1'}});
sandbox.stub(api.settings.cache, 'get').returns(-1);
});
it('Will not add limit if postsPerPage is not valid', function (done) {

View file

@ -3,20 +3,27 @@ var moment = require('moment'),
sinon = require('sinon'),
Promise = require('bluebird'),
_ = require('lodash'),
// Stuff we are testing
api = require('../../../../server/api'),
frontend = require('../../../../server/controllers/frontend'),
configUtils = require('../../../utils/configUtils'),
settingsCache = api.settings.cache,
sandbox = sinon.sandbox.create();
describe('Frontend Controller', function () {
var adminEditPagePath = '/ghost/editor/';
var adminEditPagePath = '/ghost/editor/', localSettingsCache = {permalinks: '/:slug/'};
afterEach(function () {
sandbox.restore();
configUtils.restore();
localSettingsCache = {
permalinks: '/:slug/'
};
});
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
// Helper function to prevent unit tests
@ -86,13 +93,8 @@ describe('Frontend Controller', function () {
var post = _.find(mockPosts, function (mock) {
return mock.posts[0].slug === args.slug;
});
return Promise.resolve(post || {posts: []});
});
configUtils.set({
theme: {
permalinks: '/:slug/'
}
return Promise.resolve(post || {posts: []});
});
casper = {
@ -118,14 +120,6 @@ describe('Frontend Controller', function () {
describe('static pages', function () {
describe('custom page templates', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:slug/'
}
});
});
it('it will render a custom page-slug template if it exists', function (done) {
configUtils.set({paths: {availableThemes: {casper: casper}}});
req.path = '/' + mockPosts[2].posts[0].slug + '/';
@ -173,14 +167,6 @@ describe('Frontend Controller', function () {
});
describe('permalink set to slug', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:slug/'
}
});
});
it('will render static page via /:slug/', function (done) {
configUtils.set({paths: {availableThemes: {casper: casper}}});
@ -247,11 +233,7 @@ describe('Frontend Controller', function () {
describe('permalink set to date', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:year/:month/:day/:slug/'
}
});
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
});
it('will render static page via /:slug', function (done) {
@ -307,12 +289,6 @@ describe('Frontend Controller', function () {
describe('post', function () {
describe('permalink set to slug', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:slug/'
}
});
mockPosts[1].posts[0].url = '/' + mockPosts[1].posts[0].slug + '/';
});
@ -399,11 +375,7 @@ describe('Frontend Controller', function () {
describe('permalink set to date', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:year/:month/:day/:slug/'
}
});
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
var date = moment(mockPosts[1].posts[0].published_at).format('YYYY/MM/DD');
mockPosts[1].posts[0].url = '/' + date + '/' + mockPosts[1].posts[0].slug + '/';
@ -446,6 +418,7 @@ describe('Frontend Controller', function () {
// Handle Edit append
it('will redirect post to admin edit page via /YYYY/MM/DD/:slug/edit/', function (done) {
var dateFormat = moment(mockPosts[1].posts[0].published_at).format('YYYY/MM/DD');
req.path = '/' + [dateFormat, mockPosts[1].posts[0].slug, 'edit'].join('/') + '/';
res.redirect = function (arg) {
res.render.called.should.be.false();
@ -479,11 +452,7 @@ describe('Frontend Controller', function () {
describe('permalink set to author', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: 'author/:slug/'
}
});
localSettingsCache.permalinks = 'author/:slug/';
// set post url to permalink-defined url
mockPosts[1].posts[0].url = '/test/' + mockPosts[1].posts[0].slug + '/';
@ -569,11 +538,7 @@ describe('Frontend Controller', function () {
describe('permalink set to custom format', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:year/:slug/'
}
});
localSettingsCache.permalinks = '/:year/:slug/';
configUtils.set({paths: {availableThemes: {casper: casper}}});
@ -686,11 +651,7 @@ describe('Frontend Controller', function () {
describe('permalink set to custom format no slash', function () {
beforeEach(function () {
configUtils.set({
theme: {
permalinks: '/:year/:slug/'
}
});
localSettingsCache.permalinks = '/:year/:slug/';
var date = moment(mockPosts[1].posts[0].published_at).format('YYYY');
mockPosts[1].posts[0].url = '/' + date + '/' + mockPosts[1].posts[0].slug + '/';
@ -780,12 +741,6 @@ describe('Frontend Controller', function () {
return Promise.resolve(post || {posts: []});
});
configUtils.set({
theme: {
permalinks: '/:slug/'
}
});
req = {
app: {get: function () {return 'casper'; }},
path: '/', params: {}, route: {}

View file

@ -2,28 +2,31 @@ var should = require('should'),
sinon = require('sinon'),
Promise = require('bluebird'),
configUtils = require('../../../utils/configUtils'),
// Things we are testing
api = require('../../../../server/api'),
postLookup = require('../../../../server/controllers/frontend/post-lookup'),
settingsCache = api.settings.cache,
sandbox = sinon.sandbox.create();
describe('postLookup', function () {
var postAPIStub;
var postAPIStub, localSettingsCache = {};
afterEach(function () {
sandbox.restore();
configUtils.restore();
localSettingsCache = {};
});
beforeEach(function () {
postAPIStub = sandbox.stub(api.posts, 'read');
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
describe('Permalinks: /:slug/', function () {
beforeEach(function () {
configUtils.set({theme: {permalinks: '/:slug/'}});
localSettingsCache.permalinks = '/:slug/';
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
.returns(new Promise.resolve({posts: [{
@ -79,7 +82,7 @@ describe('postLookup', function () {
describe('Permalinks: /:year/:month/:day/:slug/', function () {
beforeEach(function () {
configUtils.set({theme: {permalinks: '/:year/:month/:day/:slug/'}});
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
.returns(new Promise.resolve({posts: [{
@ -135,7 +138,7 @@ describe('postLookup', function () {
describe('Edit URLs', function () {
beforeEach(function () {
configUtils.set({theme: {permalinks: '/:slug/'}});
localSettingsCache.permalinks = '/:slug/';
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
.returns(new Promise.resolve({posts: [{
@ -192,9 +195,10 @@ describe('postLookup', function () {
}).catch(done);
});
});
describe('AMP URLs', function () {
beforeEach(function () {
configUtils.set({theme: {permalinks: '/:slug/'}});
localSettingsCache.permalinks = '/:slug/';
postAPIStub.withArgs({slug: 'welcome-to-ghost', include: 'author,tags'})
.returns(new Promise.resolve({posts: [{

View file

@ -1,4 +1,3 @@
/* globals describe, beforeEach, afterEach, it */
var should = require('should'),
ghostUrl = require('../../shared/ghost-url'),
configUtils = require('../utils/configUtils'),

View file

@ -1,10 +1,11 @@
var should = require('should'),
Promise = require('bluebird'),
// Stuff we are testing
sinon = require('sinon'),
mail = require('../../../server/mail'),
api = require('../../../server/api'),
configUtils = require('../../utils/configUtils'),
i18n = require('../../../server/i18n'),
sandbox = sinon.sandbox.create(),
mailer,
// Mock SMTP config
@ -40,8 +41,8 @@ i18n.init();
describe('Mail: Ghostmailer', function () {
afterEach(function () {
mailer = null;
configUtils.restore();
sandbox.restore();
});
it('should attach mail provider to ghost instance', function () {
@ -177,19 +178,22 @@ describe('Mail: Ghostmailer', function () {
});
it('should fall back to [blog.title] <ghost@[blog.url]>', function () {
sandbox.stub(api.settings.cache, 'get').returns('Test');
// Standard domain
configUtils.set({url: 'http://default.com', mail: {from: null}, theme: {title: 'Test'}});
configUtils.set({url: 'http://default.com', mail: {from: null}});
mailer = new mail.GhostMailer();
mailer.from().should.equal('"Test" <ghost@default.com>');
// Trailing slash
configUtils.set({url: 'http://default.com/', mail: {from: null}, theme: {title: 'Test'}});
configUtils.set({url: 'http://default.com/', mail: {from: null}});
mailer.from().should.equal('"Test" <ghost@default.com>');
// Strip Port
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}, theme: {title: 'Test'}});
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}});
mailer.from().should.equal('"Test" <ghost@default.com>');
});
@ -203,41 +207,43 @@ describe('Mail: Ghostmailer', function () {
});
it('should attach blog title if from or fromaddress are only email addresses', function () {
sandbox.stub(api.settings.cache, 'get').returns('Test');
// from and fromaddress are both set
configUtils.set({mail: {from: 'from@default.com', fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
configUtils.set({mail: {from: 'from@default.com', fromaddress: 'fa@default.com'}});
mailer = new mail.GhostMailer();
mailer.from().should.equal('"Test" <from@default.com>');
// only from set
configUtils.set({mail: {from: 'from@default.com', fromaddress: null}, theme: {title: 'Test'}});
configUtils.set({mail: {from: 'from@default.com', fromaddress: null}});
mailer.from().should.equal('"Test" <from@default.com>');
// only fromaddress set
configUtils.set({mail: {from: null, fromaddress: 'fa@default.com'}, theme: {title: 'Test'}});
configUtils.set({mail: {from: null, fromaddress: 'fa@default.com'}});
mailer.from().should.equal('"Test" <fa@default.com>');
});
it('should ignore theme title if from address is Title <email@address.com> format', function () {
// from and fromaddress are both set
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: '"C3PO" <fa@default.com>'}});
mailer = new mail.GhostMailer();
mailer.from().should.equal('"R2D2" <from@default.com>');
// only from set
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: null}, theme: {title: 'Test'}});
configUtils.set({mail: {from: '"R2D2" <from@default.com>', fromaddress: null}});
mailer.from().should.equal('"R2D2" <from@default.com>');
// only fromaddress set
configUtils.set({mail: {from: null, fromaddress: '"C3PO" <fa@default.com>'}, theme: {title: 'Test'}});
configUtils.set({mail: {from: null, fromaddress: '"C3PO" <fa@default.com>'}});
mailer.from().should.equal('"C3PO" <fa@default.com>');
});
it('should use default title if not theme title is provided', function () {
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}, theme: {title: null}});
configUtils.set({url: 'http://default.com:2368/', mail: {from: null}});
mailer = new mail.GhostMailer();

View file

@ -1,10 +1,11 @@
var getAuthorImage = require('../../../server/data/meta/author_image'),
should = require('should'),
configUtils = require('../../utils/configUtils');
var should = require('should'),
sinon = require('sinon'),
getAuthorImage = require('../../../server/data/meta/author_image'),
sandbox = sinon.sandbox.create();
describe('getAuthorImage', function () {
afterEach(function () {
configUtils.restore();
sandbox.restore();
});
it('should return author image url if post and has url', function () {
@ -16,6 +17,7 @@ describe('getAuthorImage', function () {
}
}
}, false);
imageUrl.should.equal('/content/images/2016/01/myimage.jpg');
});
@ -66,6 +68,7 @@ describe('getAuthorImage', function () {
}
}
});
should(imageUrl).equal(null);
});
@ -74,6 +77,7 @@ describe('getAuthorImage', function () {
context: ['post'],
post: {}
});
should(imageUrl).equal(null);
});
@ -81,21 +85,7 @@ describe('getAuthorImage', function () {
var imageUrl = getAuthorImage({
context: ['tag']
});
should(imageUrl).equal(null);
});
it('should return config theme author image if context is a post and no post',
function () {
configUtils.set({
theme: {
author: {
image: '/content/images/2016/01/myimage.jpg'
}
}
});
var imageUrl = getAuthorImage({
context: ['post']
});
imageUrl.should.match(/\/content\/images\/2016\/01\/myimage\.jpg$/);
});
});

View file

@ -1,6 +1,8 @@
var should = require('should'),
sinon = require('sinon'),
getContextObject = require('../../../server/data/meta/context_object.js'),
configUtils = require('../../utils/configUtils');
settingsCache = require('../../../server/api/settings').cache,
sandbox = sinon.sandbox.create();
describe('getContextObject', function () {
var data, context, contextObject;
@ -47,11 +49,15 @@ describe('getContextObject', function () {
describe('override blog', function () {
before(function () {
configUtils.set({theme: {foo: 'bar'}});
sandbox.stub(settingsCache, 'get', function (key) {
return {
cover: 'test.png'
}[key];
});
});
after(function () {
configUtils.restore();
sandbox.restore();
});
it('should return blog context object for unknown context', function () {
@ -60,7 +66,7 @@ describe('getContextObject', function () {
contextObject = getContextObject(data, context);
should.exist(contextObject);
contextObject.should.have.property('foo', 'bar');
contextObject.should.have.property('cover', 'test.png');
});
});
});

View file

@ -1,9 +1,24 @@
var getTitle = require('../../../server/data/meta/title'),
configUtils = require('../../utils/configUtils');
var sinon = require('sinon'),
should = require('should'),
getTitle = require('../../../server/data/meta/title'),
settingsCache = require('../../../server/api/settings').cache,
sandbox = sinon.sandbox.create();
should.equal(true, true);
describe('getTitle', function () {
var localSettingsCache = {};
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
afterEach(function () {
configUtils.restore();
sandbox.restore();
localSettingsCache = {};
});
it('should return meta_title if on data root', function () {
@ -15,36 +30,26 @@ describe('getTitle', function () {
});
it('should return blog title if on home', function () {
configUtils.set({
theme: {
title: 'My blog title'
}
});
localSettingsCache.title = 'My blog title';
var title = getTitle({}, {context: 'home'});
title.should.equal('My blog title');
});
it('should return author name - blog title if on data author page', function () {
configUtils.set({
theme: {
title: 'My blog title 2'
}
});
localSettingsCache.title = 'My blog title 2';
var title = getTitle({
author: {
name: 'Author Name'
}
}, {context: ['author']});
title.should.equal('Author Name - My blog title 2');
});
it('should return author page title if on data author page with more then one page', function () {
configUtils.set({
theme: {
title: 'My blog title 2'
}
});
localSettingsCache.title = 'My blog title 2';
var title = getTitle({
author: {
@ -62,11 +67,7 @@ describe('getTitle', function () {
});
it('should return tag name - blog title if on data tag page no meta_title', function () {
configUtils.set({
theme: {
title: 'My blog title 3'
}
});
localSettingsCache.title = 'My blog title 3';
var title = getTitle({
tag: {
@ -78,11 +79,7 @@ describe('getTitle', function () {
});
it('should return tag name - page - blog title if on data tag page no meta_title', function () {
configUtils.set({
theme: {
title: 'My blog title 3'
}
});
localSettingsCache.title = 'My blog title 3';
var title = getTitle({
tag: {
@ -126,6 +123,7 @@ describe('getTitle', function () {
title: 'My awesome post!'
}
}, {context: ['amp', 'post']});
title.should.equal('My awesome post!');
});
@ -135,6 +133,7 @@ describe('getTitle', function () {
title: 'My awesome page!'
}
}, {context: ['page']});
title.should.equal('My awesome page!');
});
@ -144,6 +143,7 @@ describe('getTitle', function () {
title: 'My awesome page!'
}
}, {context: ['amp', 'page']});
title.should.equal('My awesome page!');
});
@ -154,6 +154,7 @@ describe('getTitle', function () {
meta_title: 'My Tag Meta Title Post! '
}
}, {context: ['post']});
title.should.equal('My Tag Meta Title Post!');
});
@ -164,15 +165,12 @@ describe('getTitle', function () {
meta_title: 'My Tag Meta Title Post! '
}
}, {context: ['amp', 'post']});
title.should.equal('My Tag Meta Title Post!');
});
it('should return blog title with page if unknown type', function () {
configUtils.set({
theme: {
title: 'My blog title 4'
}
});
localSettingsCache.title = 'My blog title 4';
var title = getTitle({}, {
context: ['paged'],

View file

@ -2,6 +2,7 @@ var sinon = require('sinon'),
should = require('should'),
express = require('express'),
serveFavicon = require('../../../server/middleware/serve-favicon'),
settingsCache = require('../../../server/api/settings').cache,
configUtils = require('../../utils/configUtils'),
path = require('path'),
sandbox = sinon.sandbox.create();
@ -9,7 +10,7 @@ var sinon = require('sinon'),
should.equal(true, true);
describe('Serve Favicon', function () {
var req, res, next, blogApp;
var req, res, next, blogApp, localSettingsCache = {};
beforeEach(function () {
req = sinon.spy();
@ -17,11 +18,16 @@ describe('Serve Favicon', function () {
next = sinon.spy();
blogApp = express();
req.app = blogApp;
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
afterEach(function () {
sandbox.restore();
configUtils.restore();
localSettingsCache = {};
});
describe('serveFavicon', function () {
@ -37,17 +43,14 @@ describe('Serve Favicon', function () {
middleware(req, res, next);
next.called.should.be.true();
});
describe('serves', function () {
it('custom uploaded favicon.png', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.png';
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: 'favicon.png'
}
});
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = 'favicon.png';
res = {
writeHead: function (statusCode) {
@ -61,16 +64,13 @@ describe('Serve Favicon', function () {
middleware(req, res, next);
});
it('custom uploaded favicon.ico', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.ico';
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: 'favicon.ico'
}
});
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = 'favicon.ico';
res = {
writeHead: function (statusCode) {
@ -84,16 +84,13 @@ describe('Serve Favicon', function () {
middleware(req, res, next);
});
it('default favicon.ico', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.ico';
configUtils.set('paths:corePath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: ''
}
});
configUtils.set('paths:corePath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = '';
res = {
writeHead: function (statusCode) {
@ -108,17 +105,14 @@ describe('Serve Favicon', function () {
middleware(req, res, next);
});
});
describe('redirects', function () {
it('to custom favicon.ico when favicon.png is requested', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.png';
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: 'favicon.ico'
}
});
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = 'favicon.ico';
res = {
redirect: function (statusCode) {
@ -129,16 +123,13 @@ describe('Serve Favicon', function () {
middleware(req, res, next);
});
it('to custom favicon.png when favicon.ico is requested', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.ico';
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: 'favicon.png'
}
});
configUtils.set('paths:contentPath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = 'favicon.png';
res = {
redirect: function (statusCode) {
@ -153,13 +144,9 @@ describe('Serve Favicon', function () {
it('to favicon.ico when favicon.png is requested', function (done) {
var middleware = serveFavicon();
req.path = '/favicon.png';
configUtils.set('paths:corePath', path.join(__dirname, '../../../test/utils/fixtures/'));
configUtils.set({
theme: {
icon: ''
}
});
configUtils.set('paths:corePath', path.join(__dirname, '../../../test/utils/fixtures/'));
localSettingsCache.icon = '';
res = {
redirect: function (statusCode) {

View file

@ -4,13 +4,9 @@ var should = require('should'),
_ = require('lodash'),
Promise = require('bluebird'),
testUtils = require('../utils'),
channelConfig = require('../../server/controllers/frontend/channel-config'),
// Things that get overridden
api = require('../../server/api'),
rss = rewire('../../server/data/xml/rss'),
configUtils = require('../utils/configUtils');
// Helper function to prevent unit tests
@ -281,6 +277,7 @@ describe('RSS', function () {
describe('dataBuilder', function () {
var apiBrowseStub, apiTagStub, apiUserStub;
beforeEach(function () {
apiBrowseStub = sandbox.stub(api.posts, 'browse', function () {
return Promise.resolve({posts: [], meta: {pagination: {pages: 3}}});
@ -306,11 +303,19 @@ describe('RSS', function () {
set: sinon.stub()
};
configUtils.set({url: 'http://my-ghost-blog.com', theme: {
title: 'Test',
description: 'Some Text',
permalinks: '/:slug/'
}});
sandbox.stub(api.settings.cache, 'get', function (key) {
var obj = {
title: 'Test',
description: 'Some Text',
permalinks: '/:slug/'
};
return obj[key];
});
configUtils.set({
url: 'http://my-ghost-blog.com'
});
});
it('should process the data correctly for the index feed', function (done) {

View file

@ -1,22 +1,28 @@
var should = require('should'),
hbs = require('express-hbs'),
sinon = require('sinon'),
utils = require('./utils'),
configUtils = require('../../utils/configUtils'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers');
helpers = require('../../../server/helpers'),
settingsCache = require('../../../server/api/settings').cache,
sandbox = sinon.sandbox.create(),
handlebars = hbs.handlebars;
describe('{{asset}} helper', function () {
var rendered;
var rendered, localSettingsCache = {};
before(function () {
utils.loadHelpers();
configUtils.set({assetHash: 'abc'});
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
after(function () {
configUtils.restore();
sandbox.restore();
});
it('has loaded asset helper', function () {
@ -37,7 +43,8 @@ describe('{{asset}} helper', function () {
});
it('handles custom favicon correctly', function () {
configUtils.set('theme:icon', '/content/images/favicon.png');
localSettingsCache.icon = '/content/images/favicon.png';
// with ghost set and png
rendered = helpers.asset('favicon.png', {hash: {ghost: 'true'}});
should.exist(rendered);
@ -48,7 +55,7 @@ describe('{{asset}} helper', function () {
should.exist(rendered);
String(rendered).should.equal('/content/images/favicon.png');
configUtils.set('theme:icon', '/content/images/favicon.ico');
localSettingsCache.icon = '/content/images/favicon.ico';
// with ghost set and ico
rendered = helpers.asset('favicon.ico', {hash: {ghost: 'true'}});
@ -62,7 +69,8 @@ describe('{{asset}} helper', function () {
});
it('handles shared assets correctly', function () {
configUtils.set('theme:icon', '');
localSettingsCache.icon = '';
// with ghost set
rendered = helpers.asset('shared/asset.js', {hash: {ghost: 'true'}});
should.exist(rendered);
@ -107,7 +115,8 @@ describe('{{asset}} helper', function () {
});
it('handles custom favicon correctly', function () {
configUtils.set('theme:icon', '/content/images/favicon.png');
localSettingsCache.icon = '/content/images/favicon.png';
// with ghost set and png
rendered = helpers.asset('favicon.png', {hash: {ghost: 'true'}});
should.exist(rendered);
@ -118,7 +127,7 @@ describe('{{asset}} helper', function () {
should.exist(rendered);
String(rendered).should.equal('/blog/content/images/favicon.png');
configUtils.set('theme:icon', '/content/images/favicon.ico');
localSettingsCache.icon = '/content/images/favicon.ico';
// with ghost set and ico
rendered = helpers.asset('favicon.ico', {hash: {ghost: 'true'}});

View file

@ -3,18 +3,15 @@ var should = require('should'),
_ = require('lodash'),
Promise = require('bluebird'),
hbs = require('express-hbs'),
moment = require('moment'),
utils = require('./utils'),
configUtils = require('../../utils/configUtils'),
moment = require('moment'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers'),
api = require('../../../server/api'),
labs = require('../../../server/utils/labs'),
sandbox = sinon.sandbox.create();
settingsCache = api.settings.cache,
handlebars = hbs.handlebars,
sandbox = sinon.sandbox.create();
describe('{{ghost_head}} helper', function () {
var settingsReadStub;
@ -46,16 +43,19 @@ describe('{{ghost_head}} helper', function () {
});
describe('without Code Injection', function () {
var localSettingsCache = {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true
};
beforeEach(function () {
configUtils.set({
url: 'http://testurl.com/',
theme: {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true
}
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
configUtils.set('url', 'http://testurl.com/');
});
it('has loaded ghost_head helper', function () {
@ -882,15 +882,10 @@ describe('{{ghost_head}} helper', function () {
describe('with /blog subdirectory', function () {
beforeEach(function () {
localSettingsCache.icon = '/content/images/favicon.png';
configUtils.set({
url: 'http://testurl.com/blog/',
theme: {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true,
icon: '/content/images/favicon.png'
}
url: 'http://testurl.com/blog/'
});
});
@ -912,16 +907,21 @@ describe('{{ghost_head}} helper', function () {
});
describe('with changed origin in config file', function () {
var localSettingsCache = {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true,
icon: '/content/images/favicon.png'
};
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
configUtils.set({
url: 'http://testurl.com/blog/',
theme: {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true,
icon: '/content/images/favicon.png'
},
referrerPolicy: 'origin'
});
});
@ -941,16 +941,21 @@ describe('{{ghost_head}} helper', function () {
});
describe('with useStructuredData is set to false in config file', function () {
var localSettingsCache = {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true,
icon: '/content/images/favicon.png'
};
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
configUtils.set({
url: 'http://testurl.com/',
theme: {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
amp: true,
icon: '/content/images/favicon.png'
},
privacy: {
useStructuredData: false
}
@ -995,19 +1000,24 @@ describe('{{ghost_head}} helper', function () {
});
describe('with Code Injection', function () {
var localSettingsCache = {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
icon: '/content/images/favicon.png'
};
beforeEach(function () {
settingsReadStub.returns(new Promise.resolve({
settings: [{value: '<style>body {background: red;}</style>'}]
}));
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
configUtils.set({
url: 'http://testurl.com/',
theme: {
title: 'Ghost',
description: 'blog description',
cover: '/content/images/blog-cover.png',
icon: '/content/images/favicon.png'
}
url: 'http://testurl.com/'
});
});
@ -1126,12 +1136,17 @@ describe('{{ghost_head}} helper', function () {
});
describe('amp is disabled', function () {
var localSettingsCache = {
amp: false
};
beforeEach(function () {
configUtils.set({
url: 'http://testurl.com/',
theme: {
amp: false
}
url: 'http://testurl.com/'
});
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});

View file

@ -1,24 +1,23 @@
var should = require('should'),
sinon = require('sinon'),
hbs = require('express-hbs'),
utils = require('./utils'),
configUtils = require('../../utils/configUtils'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers');
sandbox = sinon.sandbox.create(),
helpers = require('../../../server/helpers'),
settingsCache = require('../../../server/api/settings').cache;
describe('{{meta_description}} helper', function () {
before(function () {
utils.loadHelpers();
configUtils.set({
theme: {
description: 'Just a blogging platform.'
}
});
sandbox.stub(settingsCache, 'get').returns('Just a blogging platform.');
});
after(function () {
configUtils.restore();
sandbox.restore();
});
it('has loaded meta_description helper', function () {

View file

@ -1,24 +1,27 @@
var should = require('should'),
sinon = require('sinon'),
hbs = require('express-hbs'),
utils = require('./utils'),
configUtils = require('../../utils/configUtils'),
// Stuff we are testing
handlebars = hbs.handlebars,
helpers = require('../../../server/helpers');
sandbox = sinon.sandbox.create(),
helpers = require('../../../server/helpers'),
settingsCache = require('../../../server/api/settings').cache;
describe('{{meta_title}} helper', function () {
before(function () {
utils.loadHelpers();
configUtils.set({
theme: {
sandbox.stub(settingsCache, 'get', function (key) {
return {
title: 'Ghost'
}
}[key];
});
});
after(function () {
configUtils.restore();
sandbox.restore();
});
it('has loaded meta_title helper', function () {

View file

@ -2,9 +2,12 @@
var should = require('should'),
_ = require('lodash'),
moment = require('moment'),
sinon = require('sinon'),
utils = require('../../../server/utils'),
settingsCache = require('../../../server/api/settings').cache,
configUtils = require('../../utils/configUtils'),
testUtils = require('../../utils'),
sandbox = sinon.sandbox.create(),
config = configUtils.config;
describe('Url', function () {
@ -14,6 +17,7 @@ describe('Url', function () {
afterEach(function () {
configUtils.restore();
sandbox.restore();
});
describe('getProtectedSlugs', function () {
@ -343,9 +347,17 @@ describe('Url', function () {
});
describe('urlPathForPost', function () {
it('permalink is /:slug/, timezone is default', function () {
configUtils.set('theme:permalinks', '/:slug/');
var localSettingsCache = {
permalinks: '/:slug/'
};
beforeEach(function () {
sandbox.stub(settingsCache, 'get', function (key) {
return localSettingsCache[key];
});
});
it('permalink is /:slug/, timezone is default', function () {
var testData = testUtils.DataGenerator.Content.posts[2],
postLink = '/short-and-sweet/';
@ -353,8 +365,8 @@ describe('Url', function () {
});
it('permalink is /:year/:month/:day/:slug, blog timezone is Los Angeles', function () {
configUtils.set('theme:timezone', 'America/Los_Angeles');
configUtils.set('theme:permalinks', '/:year/:month/:day/:slug/');
localSettingsCache.activeTimezone = 'America/Los_Angeles';
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
var testData = testUtils.DataGenerator.Content.posts[2],
postLink = '/2016/05/17/short-and-sweet/';
@ -364,8 +376,8 @@ describe('Url', function () {
});
it('permalink is /:year/:month/:day/:slug, blog timezone is Asia Tokyo', function () {
configUtils.set('theme:timezone', 'Asia/Tokyo');
configUtils.set('theme:permalinks', '/:year/:month/:day/:slug/');
localSettingsCache.activeTimezone = 'Asia/Tokyo';
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
var testData = testUtils.DataGenerator.Content.posts[2],
postLink = '/2016/05/18/short-and-sweet/';
@ -375,8 +387,8 @@ describe('Url', function () {
});
it('post is page, no permalink usage allowed at all', function () {
configUtils.set('theme:timezone', 'America/Los_Angeles');
configUtils.set('theme:permalinks', '/:year/:month/:day/:slug/');
localSettingsCache.activeTimezone = 'America/Los_Angeles';
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
var testData = testUtils.DataGenerator.Content.posts[5],
postLink = '/static-page-test/';
@ -385,8 +397,8 @@ describe('Url', function () {
});
it('permalink is /:year/:id:/:author', function () {
configUtils.set('theme:timezone', 'America/Los_Angeles');
configUtils.set('theme:permalinks', '/:year/:id/:author/');
localSettingsCache.activeTimezone = 'America/Los_Angeles';
localSettingsCache.permalinks = '/:year/:id/:author/';
var testData = _.merge(testUtils.DataGenerator.Content.posts[2], {id: 3}, {author: {slug: 'joe-blog'}}),
postLink = '/2015/3/joe-blog/';
@ -396,8 +408,8 @@ describe('Url', function () {
});
it('permalink is /:year/:id:/:author', function () {
configUtils.set('theme:timezone', 'Europe/Berlin');
configUtils.set('theme:permalinks', '/:year/:id/:author/');
localSettingsCache.activeTimezone = 'Europe/Berlin';
localSettingsCache.permalinks = '/:year/:id/:author/';
var testData = _.merge(testUtils.DataGenerator.Content.posts[2], {id: 3}, {author: {slug: 'joe-blog'}}),
postLink = '/2016/3/joe-blog/';
@ -407,7 +419,7 @@ describe('Url', function () {
});
it('post is not published yet', function () {
configUtils.set('theme:permalinks', '/:year/:month/:day/:slug/');
localSettingsCache.permalinks = '/:year/:month/:day/:slug/';
var testData = _.merge(testUtils.DataGenerator.Content.posts[2], {id: 3, published_at: null}),
nowMoment = moment(),