mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 19:33:02 +03:00
New URL helper - URL consistency fixes
fixes #1765 fixes #1811 issue #1833 New UrlFor functions - moved body of url helper to config.path.urlFor, which can generate a URL for various scenarios - urlFor can take a string (name) or object (relativeUrl: '/') as the first argument - this is the first step towards issue #1833 - also added config.path.urlForPost which is async and handles getting permalink setting - frontend controller, ghost_head helper, cache invalidation all now use urlFor or urlForPost all urls should be correct and consistent URL Consistency Improvements - refactored invalidateCache into cacheInvalidationHeader which returns a promise so that url can be generated properly by urlForPost - moved isPost from models to schema, and refactored schema to have a tables object - deleted posts now return the whole object, not just id and slug, ensuring cache invalidation header can be set on delete - frontend controller rss and archive page redirects work properly with subdirectory - removes {{url}} helper from admin and client, and replaced with adminUrl helper which also uses urlFor - in res.locals ghostRoot becomes relativeUrl, and path is removed
This commit is contained in:
parent
903afc5660
commit
af6137248d
@ -29,8 +29,8 @@
|
||||
return date;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('url', function () {
|
||||
return Ghost.paths.subdir;
|
||||
Handlebars.registerHelper('adminUrl', function () {
|
||||
return Ghost.paths.subdir + '/ghost';
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('asset', function (context, options) {
|
||||
|
@ -7,6 +7,6 @@
|
||||
</div>
|
||||
<button class="button-save" type="submit">Log in</button>
|
||||
<section class="meta">
|
||||
<a class="forgotten-password" href="{{url}}/ghost/forgotten/">Forgotten password?</a>
|
||||
<a class="forgotten-password" href="{{adminUrl}}/forgotten/">Forgotten password?</a>
|
||||
</section>
|
||||
</form>
|
||||
|
@ -53,7 +53,7 @@
|
||||
<div class="no-posts-box">
|
||||
<div class="no-posts">
|
||||
<h3>You Haven't Written Any Posts Yet!</h3>
|
||||
<form action="{{url}}/ghost/editor/"><button class="button-add large" title="New Post">Write a new Post</button></form>
|
||||
<form action="{{adminUrl}}/editor/"><button class="button-add large" title="New Post">Write a new Post</button></form>
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
@ -6,7 +6,7 @@ var dataExport = require('../data/export'),
|
||||
when = require('when'),
|
||||
nodefn = require('when/node/function'),
|
||||
_ = require('underscore'),
|
||||
schema = require('../data/schema'),
|
||||
schema = require('../data/schema').tables,
|
||||
configPaths = require('../config/paths'),
|
||||
api = {},
|
||||
|
||||
|
@ -16,7 +16,7 @@ var _ = require('underscore'),
|
||||
|
||||
// ## Request Handlers
|
||||
|
||||
function invalidateCache(req, res, result) {
|
||||
function cacheInvalidationHeader(req, result) {
|
||||
var parsedUrl = req._parsedUrl.pathname.replace(/\/$/, '').split('/'),
|
||||
method = req.method,
|
||||
endpoint = parsedUrl[4],
|
||||
@ -30,15 +30,14 @@ function invalidateCache(req, res, result) {
|
||||
} else if (endpoint === 'posts') {
|
||||
cacheInvalidate = "/, /page/*, /rss/, /rss/*";
|
||||
if (id && jsonResult.slug) {
|
||||
cacheInvalidate += ', /' + jsonResult.slug + '/';
|
||||
return config.paths.urlForPost(settings, jsonResult).then(function (postUrl) {
|
||||
return cacheInvalidate + ', ' + postUrl;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (cacheInvalidate) {
|
||||
res.set({
|
||||
"X-Cache-Invalidate": cacheInvalidate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return when(cacheInvalidate);
|
||||
}
|
||||
|
||||
// ### requestHandler
|
||||
@ -52,8 +51,14 @@ requestHandler = function (apiMethod) {
|
||||
};
|
||||
|
||||
return apiMethod.call(apiContext, options).then(function (result) {
|
||||
invalidateCache(req, res, result);
|
||||
res.json(result || {});
|
||||
return cacheInvalidationHeader(req, result).then(function (header) {
|
||||
if (header) {
|
||||
res.set({
|
||||
"X-Cache-Invalidate": header
|
||||
});
|
||||
}
|
||||
});
|
||||
}, function (error) {
|
||||
var errorCode = error.errorCode || 500,
|
||||
errorMsg = {error: _.isString(error) ? error : (_.isObject(error) ? error.message : 'Unknown API Error')};
|
||||
|
@ -106,9 +106,7 @@ posts = {
|
||||
return canThis(this.user).remove.post(args.id).then(function () {
|
||||
return when(posts.read({id : args.id, status: 'all'})).then(function (result) {
|
||||
return dataProvider.Post.destroy(args.id).then(function () {
|
||||
var deletedObj = {};
|
||||
deletedObj.id = result.id;
|
||||
deletedObj.slug = result.slug;
|
||||
var deletedObj = result;
|
||||
return deletedObj;
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,11 @@
|
||||
// Contains all path information to be used throughout
|
||||
// the codebase.
|
||||
|
||||
var path = require('path'),
|
||||
var moment = require('moment'),
|
||||
path = require('path'),
|
||||
when = require('when'),
|
||||
url = require('url'),
|
||||
_ = require('underscore'),
|
||||
requireTree = require('../require-tree'),
|
||||
appRoot = path.resolve(__dirname, '../../../'),
|
||||
corePath = path.resolve(appRoot, 'core/'),
|
||||
@ -13,8 +15,9 @@ var path = require('path'),
|
||||
themeDirectories = requireTree(themePath),
|
||||
pluginDirectories = requireTree(pluginPath),
|
||||
localPath = '',
|
||||
availableThemes,
|
||||
configUrl = '',
|
||||
|
||||
availableThemes,
|
||||
availablePlugins;
|
||||
|
||||
|
||||
@ -45,6 +48,7 @@ function paths() {
|
||||
// TODO: remove configURL and give direct access to config object?
|
||||
// TODO: not called when executing tests
|
||||
function update(configURL) {
|
||||
configUrl = configURL;
|
||||
localPath = url.parse(configURL).path;
|
||||
|
||||
// Remove trailing slash
|
||||
@ -59,5 +63,129 @@ function update(configURL) {
|
||||
});
|
||||
}
|
||||
|
||||
// ## createUrl
|
||||
// Simple url creation from a given path
|
||||
// Ensures that our urls contain the subdirectory if there is one
|
||||
// And are correctly formatted as either relative or absolute
|
||||
// Usage:
|
||||
// createUrl('/', true) -> http://my-ghost-blog.com/
|
||||
// E.g. /blog/ subdir
|
||||
// createUrl('/welcome-to-ghost/') -> /blog/welcome-to-ghost/
|
||||
// Parameters:
|
||||
// - urlPath - string which must start and end with a slash
|
||||
// - absolute (optional, default:false) - boolean whether or not the url should be absolute
|
||||
// Returns:
|
||||
// - a URL which always ends with a slash
|
||||
function createUrl(urlPath, absolute) {
|
||||
urlPath = urlPath || '/';
|
||||
absolute = absolute || false;
|
||||
|
||||
var output = '';
|
||||
|
||||
// create base of url, always ends without a slash
|
||||
if (absolute) {
|
||||
output += configUrl.replace(/\/$/, '');
|
||||
} else {
|
||||
output += paths().subdir;
|
||||
}
|
||||
|
||||
// append the path, always starts and ends with a slash
|
||||
output += urlPath;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// ## urlPathForPost
|
||||
// Always sync
|
||||
// Creates the url path for a post, given a post and a permalink
|
||||
// Parameters:
|
||||
// - post - a json object representing a post
|
||||
// - permalinks - a json object containing the permalinks setting
|
||||
function urlPathForPost(post, permalinks) {
|
||||
var output = '',
|
||||
tags = {
|
||||
year: function () { return moment(post.published_at).format('YYYY'); },
|
||||
month: function () { return moment(post.published_at).format('MM'); },
|
||||
day: function () { return moment(post.published_at).format('DD'); },
|
||||
slug: function () { return post.slug; },
|
||||
id: function () { return post.id; }
|
||||
};
|
||||
|
||||
if (post.page === 1) {
|
||||
output += '/:slug/';
|
||||
} else {
|
||||
output += permalinks.value;
|
||||
}
|
||||
|
||||
// replace tags like :slug or :year with actual values
|
||||
output = output.replace(/(:[a-z]+)/g, function (match) {
|
||||
if (_.has(tags, match.substr(1))) {
|
||||
return tags[match.substr(1)]();
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// ## urlFor
|
||||
// Synchronous url creation for a given context
|
||||
// Can generate a url for a named path, given path, or known object (post)
|
||||
// Determines what sort of context it has been given, and delegates to the correct generation method,
|
||||
// Finally passing to createUrl, to ensure any subdirectory is honoured, and the url is absolute if needed
|
||||
// Usage:
|
||||
// urlFor('home', true) -> http://my-ghost-blog.com/
|
||||
// E.g. /blog/ subdir
|
||||
// urlFor({relativeUrl: '/my-static-page/') -> /blog/my-static-page/
|
||||
// E.g. if post object represents welcome post, and slugs are set to standard
|
||||
// urlFor('post', {...}) -> /welcome-to-ghost/
|
||||
// E.g. if post object represents welcome post, and slugs are set to date
|
||||
// urlFor('post', {...}) -> /2014/01/01/welcome-to-ghost/
|
||||
// Parameters:
|
||||
// - context - a string, or json object describing the context for which you need a url
|
||||
// - data (optional) - a json object containing data needed to generate a url
|
||||
// - absolute (optional, default:false) - boolean whether or not the url should be absolute
|
||||
// This is probably not the right place for this, but it's the best place for now
|
||||
function urlFor(context, data, absolute) {
|
||||
var urlPath = '/',
|
||||
knownObjects = ['post', 'tag', 'user'],
|
||||
knownPaths = {'home': '/', 'rss': '/rss/'}; // this will become really big
|
||||
|
||||
// Make data properly optional
|
||||
if (_.isBoolean(data)) {
|
||||
absolute = data;
|
||||
data = null;
|
||||
}
|
||||
|
||||
if (_.isObject(context) && context.relativeUrl) {
|
||||
urlPath = context.relativeUrl;
|
||||
} else if (_.isString(context) && _.indexOf(knownObjects, context) !== -1) {
|
||||
// trying to create a url for an object
|
||||
if (context === 'post' && data.post && data.permalinks) {
|
||||
urlPath = urlPathForPost(data.post, data.permalinks);
|
||||
}
|
||||
// other objects are recognised but not yet supported
|
||||
} else if (_.isString(context) && _.indexOf(_.keys(knownPaths), context) !== -1) {
|
||||
// trying to create a url for a named path
|
||||
urlPath = knownPaths[context] || '/';
|
||||
}
|
||||
|
||||
return createUrl(urlPath, absolute);
|
||||
}
|
||||
|
||||
// ## urlForPost
|
||||
// This method is async as we have to fetch the permalinks
|
||||
// Get the permalink setting and then get a URL for the given post
|
||||
// Parameters
|
||||
// - settings - passed reference to api.settings
|
||||
// - post - a json object representing a post
|
||||
// - absolute (optional, default:false) - boolean whether or not the url should be absolute
|
||||
function urlForPost(settings, post, absolute) {
|
||||
return settings.read('permalinks').then(function (permalinks) {
|
||||
return urlFor('post', {post: post, permalinks: permalinks}, absolute);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = paths;
|
||||
module.exports.update = update;
|
||||
module.exports.urlFor = urlFor;
|
||||
module.exports.urlForPost = urlForPost;
|
||||
|
@ -25,19 +25,14 @@ frontendControllers = {
|
||||
postsPerPage,
|
||||
options = {};
|
||||
|
||||
api.settings.read('postsPerPage').then(function (postPP) {
|
||||
postsPerPage = parseInt(postPP.value, 10);
|
||||
// No negative pages
|
||||
if (isNaN(pageParam) || pageParam < 1) {
|
||||
//redirect to 404 page?
|
||||
return res.redirect('/');
|
||||
}
|
||||
options.page = pageParam;
|
||||
// No negative pages, or page 1
|
||||
if (isNaN(pageParam) || pageParam < 1 || (pageParam === 1 && req.route.path === '/page/:page/')) {
|
||||
return res.redirect(config.paths().subdir + '/');
|
||||
}
|
||||
|
||||
// Redirect '/page/1/' to '/' for all teh good SEO
|
||||
if (pageParam === 1 && req.route.path === '/page/:page/') {
|
||||
return res.redirect(config.paths().subdir + '/');
|
||||
}
|
||||
return api.settings.read('postsPerPage').then(function (postPP) {
|
||||
postsPerPage = parseInt(postPP.value, 10);
|
||||
options.page = pageParam;
|
||||
|
||||
// No negative posts per page, must be number
|
||||
if (!isNaN(postsPerPage) && postsPerPage > 0) {
|
||||
@ -138,39 +133,39 @@ frontendControllers = {
|
||||
},
|
||||
'rss': function (req, res, next) {
|
||||
// Initialize RSS
|
||||
var siteUrl = config().url,
|
||||
pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1,
|
||||
var pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1,
|
||||
feed;
|
||||
|
||||
// No negative pages, or page 1
|
||||
if (isNaN(pageParam) || pageParam < 1 || (pageParam === 1 && req.route.path === '/rss/:page/')) {
|
||||
return res.redirect(config.paths().subdir + '/rss/');
|
||||
}
|
||||
|
||||
//needs refact for multi user to not use first user as default
|
||||
when.settle([
|
||||
return when.settle([
|
||||
api.users.read({id : 1}),
|
||||
api.settings.read('title'),
|
||||
api.settings.read('description')
|
||||
api.settings.read('description'),
|
||||
api.settings.read('permalinks')
|
||||
]).then(function (result) {
|
||||
var user = result[0].value,
|
||||
title = result[1].value.value,
|
||||
description = result[2].value.value;
|
||||
description = result[2].value.value,
|
||||
permalinks = result[3].value,
|
||||
siteUrl = config.paths.urlFor('home', null, true),
|
||||
feedUrl = config.paths.urlFor('rss', null, true);
|
||||
|
||||
feed = new RSS({
|
||||
title: title,
|
||||
description: description,
|
||||
generator: 'Ghost v' + res.locals.version,
|
||||
author: user ? user.name : null,
|
||||
feed_url: url.resolve(siteUrl, '/rss/'),
|
||||
feed_url: feedUrl,
|
||||
site_url: siteUrl,
|
||||
ttl: '60'
|
||||
});
|
||||
|
||||
// No negative pages
|
||||
if (isNaN(pageParam) || pageParam < 1) {
|
||||
return res.redirect(config.paths().subdir + '/rss/');
|
||||
}
|
||||
|
||||
if (pageParam === 1 && req.route.path === config.paths().subdir + '/rss/:page/') {
|
||||
return res.redirect(config.paths().subdir + '/rss/');
|
||||
}
|
||||
|
||||
api.posts.browse({page: pageParam}).then(function (page) {
|
||||
return api.posts.browse({page: pageParam}).then(function (page) {
|
||||
var maxPage = page.pages,
|
||||
feedItems = [];
|
||||
|
||||
@ -187,37 +182,35 @@ frontendControllers = {
|
||||
|
||||
filters.doFilter('prePostsRender', page.posts).then(function (posts) {
|
||||
posts.forEach(function (post) {
|
||||
var deferred = when.defer();
|
||||
post.url = coreHelpers.url;
|
||||
post.url().then(function (postUrl) {
|
||||
var item = {
|
||||
title: _.escape(post.title),
|
||||
guid: post.uuid,
|
||||
url: siteUrl + postUrl,
|
||||
date: post.published_at,
|
||||
categories: _.pluck(post.tags, 'name')
|
||||
},
|
||||
content = post.html;
|
||||
var deferred = when.defer(),
|
||||
item = {
|
||||
title: _.escape(post.title),
|
||||
guid: post.uuid,
|
||||
url: config.paths.urlFor('post', {post: post, permalinks: permalinks}, true),
|
||||
date: post.published_at,
|
||||
categories: _.pluck(post.tags, 'name')
|
||||
},
|
||||
content = post.html;
|
||||
|
||||
//set img src to absolute url
|
||||
content = content.replace(/src=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||
/*jslint unparam:true*/
|
||||
p1 = url.resolve(siteUrl, p1);
|
||||
return "src='" + p1 + "' ";
|
||||
});
|
||||
//set a href to absolute url
|
||||
content = content.replace(/href=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||
/*jslint unparam:true*/
|
||||
p1 = url.resolve(siteUrl, p1);
|
||||
return "href='" + p1 + "' ";
|
||||
});
|
||||
item.description = content;
|
||||
feed.item(item);
|
||||
deferred.resolve();
|
||||
//set img src to absolute url
|
||||
content = content.replace(/src=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||
/*jslint unparam:true*/
|
||||
p1 = url.resolve(siteUrl, p1);
|
||||
return "src='" + p1 + "' ";
|
||||
});
|
||||
//set a href to absolute url
|
||||
content = content.replace(/href=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||
/*jslint unparam:true*/
|
||||
p1 = url.resolve(siteUrl, p1);
|
||||
return "href='" + p1 + "' ";
|
||||
});
|
||||
item.description = content;
|
||||
feed.item(item);
|
||||
deferred.resolve();
|
||||
feedItems.push(deferred.promise);
|
||||
});
|
||||
});
|
||||
|
||||
when.all(feedItems).then(function () {
|
||||
res.set('Content-Type', 'text/xml');
|
||||
res.send(feed.xml());
|
||||
|
@ -2,7 +2,7 @@ var when = require('when'),
|
||||
_ = require('underscore'),
|
||||
migration = require('../migration'),
|
||||
knex = require('../../models/base').knex,
|
||||
schema = require('../schema'),
|
||||
schema = require('../schema').tables,
|
||||
|
||||
excludedTables = ['sessions'],
|
||||
exporter;
|
||||
|
@ -8,7 +8,7 @@ var _ = require('underscore'),
|
||||
defaultSettings = require('../default-settings'),
|
||||
Settings = require('../../models/settings').Settings,
|
||||
fixtures = require('../fixtures'),
|
||||
schema = require('../schema'),
|
||||
schema = require('../schema').tables,
|
||||
|
||||
initialVersion = '000',
|
||||
schemaTables = _.keys(schema),
|
||||
|
@ -118,4 +118,12 @@ var db = {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = db;
|
||||
function isPost(jsonData) {
|
||||
return jsonData.hasOwnProperty('html') && jsonData.hasOwnProperty('markdown')
|
||||
&& jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug');
|
||||
}
|
||||
|
||||
module.exports.tables = db;
|
||||
module.exports.checks = {
|
||||
isPost: isPost
|
||||
};
|
@ -10,8 +10,8 @@ var downsize = require('downsize'),
|
||||
config = require('../config'),
|
||||
errors = require('../errorHandling'),
|
||||
filters = require('../filters'),
|
||||
models = require('../models'),
|
||||
template = require('./template'),
|
||||
schema = require('../data/schema').checks,
|
||||
|
||||
assetTemplate = _.template('<%= source %>?v=<%= version %>'),
|
||||
scriptTemplate = _.template('<script src="<%= source %>?v=<%= version %>"></script>'),
|
||||
@ -80,7 +80,7 @@ coreHelpers.encode = function (context, str) {
|
||||
//
|
||||
coreHelpers.pageUrl = function (context, block) {
|
||||
/*jslint unparam:true*/
|
||||
return context === 1 ? '/' : ('/page/' + context + '/');
|
||||
return config.paths().subdir + (context === 1 ? '/' : ('/page/' + context + '/'));
|
||||
};
|
||||
|
||||
// ### URL helper
|
||||
@ -93,36 +93,13 @@ coreHelpers.pageUrl = function (context, block) {
|
||||
// i.e. If inside a post context will return post permalink
|
||||
// absolute flag outputs absolute URL, else URL is relative
|
||||
coreHelpers.url = function (options) {
|
||||
var output = '',
|
||||
self = this,
|
||||
tags = {
|
||||
year: function () { return moment(self.published_at).format('YYYY'); },
|
||||
month: function () { return moment(self.published_at).format('MM'); },
|
||||
day: function () { return moment(self.published_at).format('DD'); },
|
||||
slug: function () { return self.slug; },
|
||||
id: function () { return self.id; }
|
||||
},
|
||||
isAbsolute = options && options.hash.absolute;
|
||||
return api.settings.read('permalinks').then(function (permalinks) {
|
||||
if (isAbsolute) {
|
||||
output += config().url.replace(/\/$/, '');
|
||||
} else {
|
||||
output += config.paths().subdir;
|
||||
}
|
||||
if (models.isPost(self)) {
|
||||
if (self.page === 1) {
|
||||
output += '/:slug/';
|
||||
} else {
|
||||
output += permalinks.value;
|
||||
}
|
||||
output = output.replace(/(:[a-z]+)/g, function (match) {
|
||||
if (_.has(tags, match.substr(1))) {
|
||||
return tags[match.substr(1)]();
|
||||
}
|
||||
});
|
||||
}
|
||||
return output;
|
||||
});
|
||||
var absolute = options && options.hash.absolute;
|
||||
|
||||
if (schema.isPost(this)) {
|
||||
return config.paths.urlForPost(api.settings, this, absolute);
|
||||
}
|
||||
|
||||
return when(config.paths.urlFor(this, absolute));
|
||||
};
|
||||
|
||||
// ### Asset helper
|
||||
@ -317,9 +294,9 @@ coreHelpers.body_class = function (options) {
|
||||
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
|
||||
page = this.post && this.post.page ? this.post.page : this.page || false;
|
||||
|
||||
if (_.isString(this.ghostRoot) && this.ghostRoot.match(/\/page/)) {
|
||||
if (_.isString(this.relativeUrl) && this.relativeUrl.match(/\/page/)) {
|
||||
classes.push('archive-template');
|
||||
} else if (!this.ghostRoot || this.ghostRoot === '/' || this.ghostRoot === '') {
|
||||
} else if (!this.relativeUrl || this.relativeUrl === '/' || this.relativeUrl === '') {
|
||||
classes.push('home-template');
|
||||
} else {
|
||||
classes.push('post-template');
|
||||
@ -366,7 +343,8 @@ coreHelpers.post_class = function (options) {
|
||||
|
||||
coreHelpers.ghost_head = function (options) {
|
||||
/*jslint unparam:true*/
|
||||
var blog = config.theme(),
|
||||
var self = this,
|
||||
blog = config.theme(),
|
||||
head = [],
|
||||
majorMinor = /^(\d+\.)?(\d+)/,
|
||||
trimmedVersion = this.version;
|
||||
@ -376,13 +354,13 @@ coreHelpers.ghost_head = function (options) {
|
||||
head.push('<meta name="generator" content="Ghost ' + trimmedVersion + '" />');
|
||||
|
||||
head.push('<link rel="alternate" type="application/rss+xml" title="'
|
||||
+ _.escape(blog.title) + '" href="' + config.paths().subdir + '/rss/' + '">');
|
||||
+ _.escape(blog.title) + '" href="' + config.paths.urlFor('rss') + '">');
|
||||
|
||||
if (this.ghostRoot) {
|
||||
head.push('<link rel="canonical" href="' + config().url + this.ghostRoot + '" />');
|
||||
}
|
||||
return coreHelpers.url.call(self, {hash: {absolute: true}}).then(function (url) {
|
||||
head.push('<link rel="canonical" href="' + url + '" />');
|
||||
|
||||
return filters.doFilter('ghost_head', head).then(function (head) {
|
||||
return filters.doFilter('ghost_head', head);
|
||||
}).then(function (head) {
|
||||
var headString = _.reduce(head, function (memo, item) { return memo + '\n' + item; }, '');
|
||||
return new hbs.handlebars.SafeString(headString.trim());
|
||||
});
|
||||
@ -408,8 +386,8 @@ coreHelpers.meta_title = function (options) {
|
||||
var title,
|
||||
blog;
|
||||
|
||||
if (_.isString(this.ghostRoot)) {
|
||||
if (!this.ghostRoot || this.ghostRoot === '/' || this.ghostRoot === '' || this.ghostRoot.match(/\/page/)) {
|
||||
if (_.isString(this.relativeUrl)) {
|
||||
if (!this.relativeUrl || this.relativeUrl === '/' || this.relativeUrl === '' || this.relativeUrl.match(/\/page/)) {
|
||||
blog = config.theme();
|
||||
title = blog.title;
|
||||
} else {
|
||||
@ -428,8 +406,8 @@ coreHelpers.meta_description = function (options) {
|
||||
var description,
|
||||
blog;
|
||||
|
||||
if (_.isString(this.ghostRoot)) {
|
||||
if (!this.ghostRoot || this.ghostRoot === '/' || this.ghostRoot === '' || this.ghostRoot.match(/\/page/)) {
|
||||
if (_.isString(this.relativeUrl)) {
|
||||
if (!this.relativeUrl || this.relativeUrl === '/' || this.relativeUrl === '' || this.relativeUrl.match(/\/page/)) {
|
||||
blog = config.theme();
|
||||
description = blog.description;
|
||||
} else {
|
||||
@ -572,6 +550,16 @@ coreHelpers.helperMissing = function (arg) {
|
||||
errors.logError('Missing helper: "' + arg + '"');
|
||||
};
|
||||
|
||||
// ## Admin URL helper
|
||||
// uses urlFor to generate a URL for either the admin or the frontend.
|
||||
coreHelpers.adminUrl = function (options) {
|
||||
var absolute = options && options.hash && options.hash.absolute,
|
||||
// Ghost isn't a named route as currently it violates the must start-and-end with slash rule
|
||||
context = !options || !options.hash || !options.hash.frontend ? {relativeUrl: '/ghost'} : 'home';
|
||||
|
||||
return config.paths.urlFor(context, absolute);
|
||||
};
|
||||
|
||||
// Register an async handlebars helper for a given handlebars instance
|
||||
function registerAsyncHelper(hbs, name, fn) {
|
||||
hbs.registerAsyncHelper(name, function (options, cb) {
|
||||
@ -607,7 +595,6 @@ function registerAsyncAdminHelper(name, fn) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
registerHelpers = function (adminHbs, assetHash) {
|
||||
|
||||
// Expose hbs instance for admin
|
||||
@ -662,7 +649,7 @@ registerHelpers = function (adminHbs, assetHash) {
|
||||
|
||||
registerAdminHelper('fileStorage', coreHelpers.fileStorage);
|
||||
|
||||
registerAsyncAdminHelper('url', coreHelpers.url);
|
||||
registerAdminHelper('adminUrl', coreHelpers.adminUrl);
|
||||
|
||||
};
|
||||
|
||||
|
@ -33,9 +33,8 @@ function ghostLocals(req, res, next) {
|
||||
// Make sure we have a locals value.
|
||||
res.locals = res.locals || {};
|
||||
res.locals.version = packageInfo.version;
|
||||
res.locals.path = req.path;
|
||||
// Strip off the subdir part of the path
|
||||
res.locals.ghostRoot = req.path.replace(config.paths().subdir, '');
|
||||
// relative path from the URL, not including subdir
|
||||
res.locals.relativeUrl = req.path.replace(config.paths().subdir, '');
|
||||
|
||||
if (res.isAdmin) {
|
||||
res.locals.csrfToken = req.csrfToken();
|
||||
|
@ -35,9 +35,5 @@ module.exports = {
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
isPost: function (jsonData) {
|
||||
return jsonData.hasOwnProperty('html') && jsonData.hasOwnProperty('markdown')
|
||||
&& jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug');
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
<section class="content-filter">
|
||||
<small>All Posts</small>
|
||||
</section>
|
||||
<a href="{{url}}/ghost/editor/" class="button button-add" title="New Post"><span class="hidden">New Post</span></a>
|
||||
<a href="{{adminUrl}}/editor/" class="button button-add" title="New Post"><span class="hidden">New Post</span></a>
|
||||
</header>
|
||||
<section class="content-list-content">
|
||||
<ol></ol>
|
||||
|
@ -20,12 +20,12 @@
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label>Export</label>
|
||||
<a href="{{url}}/ghost/api/v0.1/db/" class="button-save">Export</a>
|
||||
<a href="{{adminUrl}}/api/v0.1/db/" class="button-save">Export</a>
|
||||
<p>Export the blog settings and data.</p>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<form id="settings-import" method="post" action="{{url}}/ghost/api/v0.1/db/" enctype="multipart/form-data">
|
||||
<form id="settings-import" method="post" action="{{adminUrl}}/api/v0.1/db/" enctype="multipart/form-data">
|
||||
<input type="hidden" name="_csrf" value="{{csrfToken}}" />
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
|
@ -1,9 +1,11 @@
|
||||
<header id="global-header" class="navbar">
|
||||
<a class="ghost-logo" href="{{url absolute="true"}}" data-off-canvas="left" title="{{url absolute="true"}}"><span class="hidden">Ghost </span></a>{{! TODO: Change this to actual Ghost homepage }}
|
||||
<a class="ghost-logo" href="{{adminUrl absolute="true" frontend="true"}}" data-off-canvas="left" title="{{adminUrl absolute="true" frontend="true"}}">
|
||||
<span class="hidden">Ghost </span>
|
||||
</a>
|
||||
<nav id="global-nav" role="navigation">
|
||||
<ul id="main-menu" >
|
||||
{{#each adminNav}}
|
||||
<li class="{{navClass}}{{#if selected}} active{{/if}}"><a href="{{url}}/ghost{{path}}">{{name}}</a></li>
|
||||
<li class="{{navClass}}{{#if selected}} active{{/if}}"><a href="{{adminUrl}}{{path}}">{{name}}</a></li>
|
||||
{{/each}}
|
||||
|
||||
<li id="usermenu" class="subnav">
|
||||
@ -12,11 +14,11 @@
|
||||
<span class="name">{{#if currentUser.name}}{{currentUser.name}}{{else}}{{currentUser.email}}{{/if}}</span>
|
||||
</a>
|
||||
<ul class="overlay">
|
||||
<li class="usermenu-profile"><a href="{{url}}/ghost/settings/user/">Your Profile</a></li>
|
||||
<li class="usermenu-profile"><a href="{{adminUrl}}/settings/user/">Your Profile</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="usermenu-help"><a href="http://ghost.org/forum/">Help / Support</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="usermenu-signout"><a href="{{url}}/ghost/signout/">Sign Out</a></li>
|
||||
<li class="usermenu-signout"><a href="{{adminUrl}}/signout/">Sign Out</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it */
|
||||
/*globals describe, before, after, beforeEach, afterEach, it */
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
_ = require('underscore'),
|
||||
request = require('request');
|
||||
|
||||
request = request.defaults({jar:true});
|
||||
request = request.defaults({jar: true});
|
||||
|
||||
describe('Post API', function () {
|
||||
|
||||
@ -41,284 +41,375 @@ describe('Post API', function () {
|
||||
});
|
||||
|
||||
// ## Browse
|
||||
describe('Browse', function () {
|
||||
|
||||
it('retrieves all published posts only by default', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(5);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
it('retrieves all published posts only by default', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(5);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve all published posts and pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=all'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(6);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
it('can retrieve all published posts and pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=all'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(6);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Test bits of the API we don't use in the app yet to ensure the API behaves properly
|
||||
// Test bits of the API we don't use in the app yet to ensure the API behaves properly
|
||||
|
||||
it('can retrieve all status posts and pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=all&status=all'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(8);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
it('can retrieve all status posts and pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=all&status=all'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(8);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve just published pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=true'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
it('can retrieve just published pages', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?staticPages=true'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve just draft posts', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?status=draft'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
it('can retrieve just draft posts', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/?status=draft'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.posts.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'posts');
|
||||
jsonResponse.posts.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.posts[0], 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ## Read
|
||||
|
||||
it('can retrieve a post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.page.should.eql(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve a static page', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/7/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.page.should.eql(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve non existent post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/99/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve a draft post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/5/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve a draft page', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/8/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// ## Add
|
||||
|
||||
it('can create a new draft, publish post, update post', function (done) {
|
||||
var newTitle = 'My Post',
|
||||
changedTitle = 'My Post changed',
|
||||
publishedState = 'published',
|
||||
newPost = {status: 'draft', title: newTitle, markdown: 'my post'};
|
||||
|
||||
request.post({uri: testUtils.API.getApiURL('posts/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: newPost}, function (error, response, draftPost) {
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
response.should.be.json;
|
||||
draftPost.should.exist;
|
||||
draftPost.title.should.eql(newTitle);
|
||||
draftPost.status = publishedState;
|
||||
testUtils.API.checkResponse(draftPost, 'post');
|
||||
request.put({uri: testUtils.API.getApiURL('posts/' + draftPost.id + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: draftPost}, function (error, response, publishedPost) {
|
||||
describe('Read', function () {
|
||||
it('can retrieve a post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + publishedPost.slug + '/');
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
publishedPost.should.exist;
|
||||
publishedPost.title.should.eql(newTitle);
|
||||
publishedPost.status.should.eql(publishedState);
|
||||
testUtils.API.checkResponse(publishedPost, 'post');
|
||||
request.put({uri: testUtils.API.getApiURL('posts/' + publishedPost.id + '/'),
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.page.should.eql(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can retrieve a static page', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/7/'), function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.page.should.eql(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve non existent post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/99/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve a draft post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/5/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t retrieve a draft page', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/8/'), function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// ## Add
|
||||
describe('Add', function () {
|
||||
it('can create a new draft, publish post, update post', function (done) {
|
||||
var newTitle = 'My Post',
|
||||
changedTitle = 'My Post changed',
|
||||
publishedState = 'published',
|
||||
newPost = {status: 'draft', title: newTitle, markdown: 'my post'};
|
||||
|
||||
request.post({uri: testUtils.API.getApiURL('posts/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: newPost}, function (error, response, draftPost) {
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
response.should.be.json;
|
||||
draftPost.should.exist;
|
||||
draftPost.title.should.eql(newTitle);
|
||||
draftPost.status = publishedState;
|
||||
testUtils.API.checkResponse(draftPost, 'post');
|
||||
request.put({uri: testUtils.API.getApiURL('posts/' + draftPost.id + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: publishedPost}, function (error, response, updatedPost) {
|
||||
json: draftPost}, function (error, response, publishedPost) {
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + updatedPost.slug + '/');
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + publishedPost.slug + '/');
|
||||
response.should.be.json;
|
||||
updatedPost.should.exist;
|
||||
updatedPost.title.should.eql(newTitle);
|
||||
testUtils.API.checkResponse(updatedPost, 'post');
|
||||
done();
|
||||
publishedPost.should.exist;
|
||||
publishedPost.title.should.eql(newTitle);
|
||||
publishedPost.status.should.eql(publishedState);
|
||||
testUtils.API.checkResponse(publishedPost, 'post');
|
||||
request.put({uri: testUtils.API.getApiURL('posts/' + publishedPost.id + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: publishedPost}, function (error, response, updatedPost) {
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + updatedPost.slug + '/');
|
||||
response.should.be.json;
|
||||
updatedPost.should.exist;
|
||||
updatedPost.title.should.eql(newTitle);
|
||||
testUtils.API.checkResponse(updatedPost, 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ## edit
|
||||
describe('Edit', function () {
|
||||
it('can edit a post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
var jsonResponse = JSON.parse(body),
|
||||
changedValue = 'My new Title';
|
||||
jsonResponse.should.exist;
|
||||
jsonResponse.title = changedValue;
|
||||
|
||||
it('can edit a post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
var jsonResponse = JSON.parse(body),
|
||||
changedValue = 'My new Title';
|
||||
jsonResponse.should.exist;
|
||||
jsonResponse.title = changedValue;
|
||||
request.put({uri: testUtils.API.getApiURL('posts/1/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse}, function (error, response, putBody) {
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + putBody.slug + '/');
|
||||
response.should.be.json;
|
||||
putBody.should.exist;
|
||||
putBody.title.should.eql(changedValue);
|
||||
|
||||
request.put({uri: testUtils.API.getApiURL('posts/1/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse}, function (error, response, putBody) {
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + putBody.slug + '/');
|
||||
response.should.be.json;
|
||||
putBody.should.exist;
|
||||
putBody.title.should.eql(changedValue);
|
||||
|
||||
testUtils.API.checkResponse(putBody, 'post');
|
||||
done();
|
||||
testUtils.API.checkResponse(putBody, 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ## delete
|
||||
describe('Delete', function () {
|
||||
it('can\'t edit non existent post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
var jsonResponse = JSON.parse(body),
|
||||
changedValue = 'My new Title';
|
||||
jsonResponse.title.exist;
|
||||
jsonResponse.testvalue = changedValue;
|
||||
jsonResponse.id = 99;
|
||||
request.put({uri: testUtils.API.getApiURL('posts/99/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse}, function (error, response, putBody) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
testUtils.API.checkResponseValue(putBody, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t edit non existent post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/1/'), function (error, response, body) {
|
||||
var jsonResponse = JSON.parse(body),
|
||||
changedValue = 'My new Title';
|
||||
jsonResponse.title.exist;
|
||||
jsonResponse.testvalue = changedValue;
|
||||
jsonResponse.id = 99;
|
||||
request.put({uri: testUtils.API.getApiURL('posts/99/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse}, function (error, response, putBody) {
|
||||
it('can delete a post', function (done) {
|
||||
var deletePostId = 1;
|
||||
request.del({uri: testUtils.API.getApiURL('posts/' + deletePostId + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + jsonResponse.slug + '/');
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.id.should.eql(deletePostId);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t delete a non existent post', function (done) {
|
||||
request.del({uri: testUtils.API.getApiURL('posts/99/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
testUtils.API.checkResponseValue(putBody, ['error']);
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete a new draft', function (done) {
|
||||
var newTitle = 'My Post',
|
||||
publishedState = 'draft',
|
||||
newPost = {status: publishedState, title: newTitle, markdown: 'my post'};
|
||||
|
||||
request.post({uri: testUtils.API.getApiURL('posts/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: newPost}, function (error, response, draftPost) {
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
response.should.be.json;
|
||||
draftPost.should.exist;
|
||||
draftPost.title.should.eql(newTitle);
|
||||
draftPost.status = publishedState;
|
||||
testUtils.API.checkResponse(draftPost, 'post');
|
||||
request.del({uri: testUtils.API.getApiURL('posts/' + draftPost.id + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete a post', function (done) {
|
||||
var deletePostId = 1;
|
||||
request.del({uri: testUtils.API.getApiURL('posts/' + deletePostId + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
response.should.have.status(200);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, /' + jsonResponse.slug + '/');
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['id', 'slug']);
|
||||
jsonResponse.id.should.eql(deletePostId);
|
||||
done();
|
||||
describe('Dated Permalinks', function () {
|
||||
before(function (done) {
|
||||
request.get(testUtils.API.getApiURL('settings'), function (error, response, body) {
|
||||
if (error) { done(error); }
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.permalinks = '/:year/:month/:day/:slug/';
|
||||
|
||||
request.put({
|
||||
uri: testUtils.API.getApiURL('settings/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse
|
||||
}, function (error, response, putBody) {
|
||||
if (error) { done(error); }
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can\'t delete a non existent post', function (done) {
|
||||
request.del({uri: testUtils.API.getApiURL('posts/99/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
response.should.have.status(404);
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['error']);
|
||||
done();
|
||||
after(function (done) {
|
||||
request.get(testUtils.API.getApiURL('settings'), function (error, response, body) {
|
||||
if (error) { done(error); }
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.permalinks = '/:slug/';
|
||||
|
||||
request.put({
|
||||
uri: testUtils.API.getApiURL('settings/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse
|
||||
}, function (error, response, putBody) {
|
||||
if (error) { done(error); }
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete a new draft', function (done) {
|
||||
var newTitle = 'My Post',
|
||||
publishedState = 'draft',
|
||||
newPost = {status: publishedState, title: newTitle, markdown: 'my post'};
|
||||
|
||||
request.post({uri: testUtils.API.getApiURL('posts/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: newPost}, function (error, response, draftPost) {
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
response.should.be.json;
|
||||
draftPost.should.exist;
|
||||
draftPost.title.should.eql(newTitle);
|
||||
draftPost.status = publishedState;
|
||||
testUtils.API.checkResponse(draftPost, 'post');
|
||||
request.del({uri: testUtils.API.getApiURL('posts/' + draftPost.id + '/'),
|
||||
headers: {'X-CSRF-Token': csrfToken}}, function (error, response, body) {
|
||||
it('Can read a post', function (done) {
|
||||
// nothing should have changed here
|
||||
request.get(testUtils.API.getApiURL('posts/2/'), function (error, response, body) {
|
||||
if (error) { done(error); }
|
||||
response.should.have.status(200);
|
||||
//TODO: do drafts really need a x-cache-invalidate header
|
||||
should.not.exist(response.headers['x-cache-invalidate']);
|
||||
response.should.be.json;
|
||||
|
||||
var jsonResponse = JSON.parse(body);
|
||||
jsonResponse.should.exist;
|
||||
testUtils.API.checkResponseValue(jsonResponse, ['id', 'slug']);
|
||||
testUtils.API.checkResponse(jsonResponse, 'post');
|
||||
jsonResponse.slug.should.not.match(/^\/[0-9]{4}\/[0-9]{2}\/[0-9]{2}/);
|
||||
jsonResponse.page.should.eql(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Can edit a post', function (done) {
|
||||
request.get(testUtils.API.getApiURL('posts/2/'), function (error, response, body) {
|
||||
if (error) { done(error); }
|
||||
var jsonResponse = JSON.parse(body),
|
||||
changedValue = 'My new Title';
|
||||
jsonResponse.should.exist;
|
||||
jsonResponse.title = changedValue;
|
||||
|
||||
request.put({
|
||||
uri: testUtils.API.getApiURL('posts/2/'),
|
||||
headers: {'X-CSRF-Token': csrfToken},
|
||||
json: jsonResponse
|
||||
}, function (error, response, putBody) {
|
||||
if (error) { done(error); }
|
||||
var today = new Date(),
|
||||
dd = ("0" + today.getDate()).slice(-2),
|
||||
mm = ("0" + (today.getMonth() + 1)).slice(-2),
|
||||
yyyy = today.getFullYear(),
|
||||
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/' + putBody.slug + '/';
|
||||
|
||||
response.should.have.status(200);
|
||||
response.headers['x-cache-invalidate'].should.eql('/, /page/*, /rss/, /rss/*, ' + postLink);
|
||||
response.should.be.json;
|
||||
putBody.should.exist;
|
||||
putBody.title.should.eql(changedValue);
|
||||
|
||||
testUtils.API.checkResponse(putBody, 'post');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -3,11 +3,12 @@
|
||||
*/
|
||||
/*globals url, CasperTest, casper */
|
||||
CasperTest.begin('Ensure that RSS is available', 11, function suite(test) {
|
||||
CasperTest.Routines.togglePermalinks.run('off');
|
||||
casper.thenOpen(url + 'rss/', function (response) {
|
||||
var content = this.getPageContent(),
|
||||
siteTitle = '<title><![CDATA[Ghost]]></title>',
|
||||
siteDescription = '<description><![CDATA[Just a blogging platform.]]></description>',
|
||||
siteUrl = '<link>http://127.0.0.1:2369</link>',
|
||||
siteUrl = '<link>http://127.0.0.1:2369/</link>',
|
||||
postTitle = '<![CDATA[Welcome to Ghost]]>',
|
||||
postStart = '<description><![CDATA[<p>You\'re live!',
|
||||
postEnd = 'you think :)</p>]]></description>',
|
||||
@ -41,4 +42,5 @@ CasperTest.begin('Ensures dated permalinks works with RSS', 2, function suite(te
|
||||
test.assertEqual(response.status, 200, 'Response status should be 200.');
|
||||
test.assert(content.indexOf(postLink) >= 0, 'Feed should have dated permalink.');
|
||||
});
|
||||
CasperTest.Routines.togglePermalinks.run('off');
|
||||
}, false);
|
||||
|
@ -19,4 +19,60 @@ CasperTest.begin('Test helpers on homepage', 3, function suite(test) {
|
||||
test.assertExists('article.post', 'post_class outputs correct post class');
|
||||
test.assertExists('article.tag-getting-started', 'post_class outputs correct tag class');
|
||||
});
|
||||
}, true);
|
||||
}, true);
|
||||
|
||||
CasperTest.begin('Test navigating to Post', 4, function suite(test) {
|
||||
casper.thenOpen(url, function then(response) {
|
||||
var lastPost = '.content article:last-of-type',
|
||||
lastPostLink = lastPost + ' .post-title a';
|
||||
|
||||
test.assertExists(lastPost, 'there is a last child on the page');
|
||||
test.assertSelectorHasText(lastPostLink, 'Welcome to Ghost', 'Is correct post');
|
||||
|
||||
casper.then(function testLink() {
|
||||
var link = this.evaluate(function (lastPostLink) {
|
||||
return document.querySelector(lastPostLink).getAttribute('href');
|
||||
}, lastPostLink);
|
||||
|
||||
test.assert(link === '/welcome-to-ghost/', 'Has correct link');
|
||||
});
|
||||
|
||||
casper.thenClick(lastPostLink);
|
||||
|
||||
casper.waitForResource(/welcome-to-ghost/).then(function (resource) {
|
||||
test.assert(resource.status === 200, 'resource got 200');
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
|
||||
CasperTest.begin('Test navigating to Post with date permalink', 4, function suite(test) {
|
||||
CasperTest.Routines.togglePermalinks.run('on');
|
||||
casper.thenOpen(url, function then(response) {
|
||||
var lastPost = '.content article:last-of-type',
|
||||
lastPostLink = lastPost + ' .post-title a',
|
||||
today = new Date(),
|
||||
dd = ("0" + today.getDate()).slice(-2),
|
||||
mm = ("0" + (today.getMonth() + 1)).slice(-2),
|
||||
yyyy = today.getFullYear(),
|
||||
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/welcome-to-ghost/';
|
||||
|
||||
test.assertExists(lastPost, 'there is a last child on the page');
|
||||
test.assertSelectorHasText(lastPostLink, 'Welcome to Ghost', 'Is correct post');
|
||||
|
||||
casper.then(function testLink() {
|
||||
var link = this.evaluate(function (lastPostLink) {
|
||||
return document.querySelector(lastPostLink).getAttribute('href');
|
||||
}, lastPostLink);
|
||||
|
||||
test.assert(link === postLink, 'Has correct link');
|
||||
});
|
||||
|
||||
casper.thenClick(lastPostLink);
|
||||
|
||||
casper.waitForResource(postLink).then(function (resource) {
|
||||
test.assert(resource.status === 200, 'resource got 200');
|
||||
});
|
||||
});
|
||||
CasperTest.Routines.togglePermalinks.run('off');
|
||||
}, false);
|
||||
|
||||
|
@ -6,20 +6,21 @@
|
||||
|
||||
// Tests when permalinks is set to date
|
||||
CasperTest.begin('Post page does not load as slug', 2, function suite(test) {
|
||||
casper.start(url + 'welcome-to-ghost', function then(response) {
|
||||
CasperTest.Routines.togglePermalinks.run('on');
|
||||
casper.thenOpen(url + 'welcome-to-ghost', function then(response) {
|
||||
test.assertTitle('404 — Page Not Found', 'The post should return 404 page');
|
||||
test.assertElementCount('.content .post', 0, 'There is no post on this page');
|
||||
});
|
||||
}, true);
|
||||
CasperTest.Routines.togglePermalinks.run('off');
|
||||
}, false);
|
||||
|
||||
CasperTest.begin('Post page loads', 3, function suite(test) {
|
||||
CasperTest.Routines.togglePermalinks.run('off');
|
||||
casper.thenOpen(url + 'welcome-to-ghost', function then(response) {
|
||||
test.assertTitle('Welcome to Ghost', 'The post should have a title and it should be "Welcome to Ghost"');
|
||||
test.assertElementCount('.content .post', 1, 'There is exactly one post on this page');
|
||||
test.assertSelectorHasText('.poweredby', 'Proudly published with Ghost');
|
||||
});
|
||||
}, false);
|
||||
}, true);
|
||||
|
||||
CasperTest.begin('Test helpers on welcome post', 4, function suite(test) {
|
||||
casper.start(url + 'welcome-to-ghost', function then(response) {
|
||||
|
@ -289,7 +289,6 @@ describe('Frontend Routing', function () {
|
||||
// // get today's date
|
||||
// var date = moment().format("YYYY/MM/DD");
|
||||
//
|
||||
// console.log('date', date);
|
||||
//
|
||||
// request.get('/' + date + '/welcome-to-ghost/')
|
||||
// .expect(200)
|
||||
|
@ -8,6 +8,8 @@ var should = require('should'),
|
||||
_ = require('underscore'),
|
||||
rewire = require("rewire"),
|
||||
|
||||
testUtils = require('../utils'),
|
||||
|
||||
// Thing we are testing
|
||||
defaultConfig = require('../../../config.example')[process.env.NODE_ENV],
|
||||
loader = rewire('../../server/config/loader'),
|
||||
@ -274,11 +276,10 @@ describe('Config', function () {
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
sandbox.restore();
|
||||
paths.update(defaultConfig.url)
|
||||
.then(done)
|
||||
.then(null, done);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('should have exactly the right keys', function () {
|
||||
@ -346,4 +347,243 @@ describe('Config', function () {
|
||||
}).otherwise(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('urlFor', function () {
|
||||
|
||||
afterEach(function (done) {
|
||||
paths.update(defaultConfig.url)
|
||||
.then(done)
|
||||
.then(null, done);
|
||||
});
|
||||
|
||||
it('should return the home url with no options', function (done) {
|
||||
paths.urlFor().should.equal('/');
|
||||
paths.update('http://my-ghost-blog.com/blog').then(function () {
|
||||
paths.urlFor().should.equal('/blog/');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return home url when asked for', function (done) {
|
||||
var testContext = 'home';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
paths.urlFor(testContext).should.equal('/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/');
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
paths.urlFor(testContext).should.equal('/blog/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return rss url when asked for', function (done) {
|
||||
var testContext = 'rss';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
paths.urlFor(testContext).should.equal('/rss/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/rss/');
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
paths.urlFor(testContext).should.equal('/blog/rss/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/rss/');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return url for a random path when asked for', function (done) {
|
||||
var testContext = {relativeUrl: '/about/'};
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
paths.urlFor(testContext).should.equal('/about/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/about/');
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
paths.urlFor(testContext).should.equal('/blog/about/');
|
||||
paths.urlFor(testContext, true).should.equal('http://my-ghost-blog.com/blog/about/');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return url for a post when asked for', function (done) {
|
||||
var testContext = 'post',
|
||||
testData = {post: testUtils.DataGenerator.Content.posts[2], permalinks: {value: '/:slug/'}};
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
paths.urlFor(testContext, testData).should.equal('/short-and-sweet/');
|
||||
paths.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/short-and-sweet/');
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
paths.urlFor(testContext, testData).should.equal('/blog/short-and-sweet/');
|
||||
paths.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog/short-and-sweet/');
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('should return url for a dated post when asked for', function (done) {
|
||||
var testContext = 'post',
|
||||
testData = {
|
||||
post: testUtils.DataGenerator.Content.posts[2],
|
||||
permalinks: {value: '/:year/:month/:day/:slug/'}
|
||||
},
|
||||
today = new Date(),
|
||||
dd = ("0" + today.getDate()).slice(-2),
|
||||
mm = ("0" + (today.getMonth() + 1)).slice(-2),
|
||||
yyyy = today.getFullYear(),
|
||||
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/short-and-sweet/';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
paths.urlFor(testContext, testData).should.equal(postLink);
|
||||
paths.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com' + postLink);
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
paths.urlFor(testContext, testData).should.equal('/blog' + postLink);
|
||||
paths.urlFor(testContext, testData, true).should.equal('http://my-ghost-blog.com/blog' + postLink);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('urlForPost', function () {
|
||||
var sandbox;
|
||||
|
||||
beforeEach(function () {
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
sandbox.restore();
|
||||
paths.update(defaultConfig.url)
|
||||
.then(done)
|
||||
.then(null, done);
|
||||
});
|
||||
|
||||
it('should output correct url for post', function (done) {
|
||||
var settings = {'read': function read() {}},
|
||||
settingsStub = sandbox.stub(settings, 'read', function () {
|
||||
return when({value: '/:slug/'});
|
||||
}),
|
||||
testData = testUtils.DataGenerator.Content.posts[2],
|
||||
postLink = '/short-and-sweet/';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal(postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com' + postLink);
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal('/blog' + postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com/blog' + postLink);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
|
||||
});
|
||||
|
||||
it('should output correct url for post with date permalink', function (done) {
|
||||
var settings = {'read': function read() {}},
|
||||
settingsStub = sandbox.stub(settings, 'read', function () {
|
||||
return when({value: '/:year/:month/:day/:slug/'});
|
||||
}),
|
||||
testData = testUtils.DataGenerator.Content.posts[2],
|
||||
today = new Date(),
|
||||
dd = ("0" + today.getDate()).slice(-2),
|
||||
mm = ("0" + (today.getMonth() + 1)).slice(-2),
|
||||
yyyy = today.getFullYear(),
|
||||
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/short-and-sweet/';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal(postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com' + postLink);
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal('/blog' + postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com/blog' + postLink);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('should output correct url for page with date permalink', function (done) {
|
||||
var settings = {'read': function read() {}},
|
||||
settingsStub = sandbox.stub(settings, 'read', function () {
|
||||
return when({value: '/:year/:month/:day/:slug/'});
|
||||
}),
|
||||
testData = testUtils.DataGenerator.Content.posts[5],
|
||||
postLink = '/static-page-test/';
|
||||
|
||||
paths.update('http://my-ghost-blog.com').then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal(postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com' + postLink);
|
||||
|
||||
return paths.update('http://my-ghost-blog.com/blog');
|
||||
}).then(function () {
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData);
|
||||
}).then(function (url) {
|
||||
url.should.equal('/blog' + postLink);
|
||||
|
||||
// next test
|
||||
return paths.urlForPost(settings, testData, true);
|
||||
}).then(function (url) {
|
||||
url.should.equal('http://my-ghost-blog.com/blog' + postLink);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
});
|
@ -26,8 +26,106 @@ describe('Frontend Controller', function () {
|
||||
});
|
||||
|
||||
|
||||
describe('homepage', function () {
|
||||
// No tests yet, shows up in coverage report
|
||||
describe('homepage redirects', function () {
|
||||
var res;
|
||||
|
||||
beforeEach(function () {
|
||||
res = {
|
||||
redirect: sandbox.spy(),
|
||||
render: sandbox.spy()
|
||||
};
|
||||
|
||||
sandbox.stub(api.posts, 'browse', function () {
|
||||
return when({posts: {}, pages: 3});
|
||||
});
|
||||
|
||||
apiSettingsStub = sandbox.stub(api.settings, 'read');
|
||||
apiSettingsStub.withArgs('postsPerPage').returns(when({
|
||||
'key': 'postsPerPage',
|
||||
'value': 6
|
||||
}));
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 0', function () {
|
||||
var req = {params: {page: -1}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 0', function () {
|
||||
var req = {params: {page: 0}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 1', function () {
|
||||
var req = {params: {page: 1}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 0 with subdirectory', function () {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 0}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/blog/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 1 with subdirectory', function () {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 1}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/blog/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to last page if page number too big', function (done) {
|
||||
var req = {params: {page: 4}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, done).then(function () {
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/page/3/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Redirects to last page if page number too big with subdirectory', function (done) {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 4}, route: {path: '/page/:page/'}};
|
||||
|
||||
frontend.homepage(req, res, done).then(function () {
|
||||
res.redirect.calledOnce.should.be.true;
|
||||
res.redirect.calledWith('/blog/page/3/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('single', function () {
|
||||
@ -358,4 +456,118 @@ describe('Frontend Controller', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rss redirects', function () {
|
||||
var res,
|
||||
apiUsersStub;
|
||||
|
||||
beforeEach(function () {
|
||||
res = {
|
||||
locals: { version: '' },
|
||||
redirect: sandbox.spy(),
|
||||
render: sandbox.spy()
|
||||
};
|
||||
|
||||
sandbox.stub(api.posts, 'browse', function () {
|
||||
return when({posts: {}, pages: 3});
|
||||
});
|
||||
|
||||
apiUsersStub = sandbox.stub(api.users, 'read').returns(when({}));
|
||||
|
||||
apiSettingsStub = sandbox.stub(api.settings, 'read');
|
||||
apiSettingsStub.withArgs('title').returns(when({
|
||||
'key': 'title',
|
||||
'value': 'Test'
|
||||
}));
|
||||
apiSettingsStub.withArgs('description').returns(when({
|
||||
'key': 'description',
|
||||
'value': 'Some Text'
|
||||
}));
|
||||
apiSettingsStub.withArgs('permalinks').returns(when({
|
||||
'key': 'permalinks',
|
||||
'value': '/:slug/'
|
||||
}));
|
||||
});
|
||||
|
||||
it('Redirects to rss if page number is 0', function () {
|
||||
var req = {params: {page: -1}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/rss/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
|
||||
});
|
||||
|
||||
it('Redirects to rss if page number is 0', function () {
|
||||
var req = {params: {page: 0}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/rss/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 1', function () {
|
||||
var req = {params: {page: 1}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/rss/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 0 with subdirectory', function () {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 0}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/blog/rss/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to home if page number is 1 with subdirectory', function () {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 1}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, null);
|
||||
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/blog/rss/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
});
|
||||
|
||||
it('Redirects to last page if page number too big', function (done) {
|
||||
var req = {params: {page: 4}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, done).then(function () {
|
||||
res.redirect.called.should.be.true;
|
||||
res.redirect.calledWith('/rss/3/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Redirects to last page if page number too big with subdirectory', function (done) {
|
||||
sandbox.stub(config, 'paths', function () { return {subdir: '/blog'}; });
|
||||
|
||||
var req = {params: {page: 4}, route: {path: '/rss/:page/'}};
|
||||
|
||||
frontend.rss(req, res, done).then(function () {
|
||||
res.redirect.calledOnce.should.be.true;
|
||||
res.redirect.calledWith('/blog/rss/3/').should.be.true;
|
||||
res.render.called.should.be.false;
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
@ -12,7 +12,7 @@ var testUtils = require('../utils'),
|
||||
|
||||
// Stuff we are testing
|
||||
handlebars = hbs.handlebars,
|
||||
helpers = require('../../server/helpers'),
|
||||
helpers = rewire('../../server/helpers'),
|
||||
config = require('../../server/config');
|
||||
|
||||
describe('Core Helpers', function () {
|
||||
@ -23,6 +23,7 @@ describe('Core Helpers', function () {
|
||||
|
||||
beforeEach(function (done) {
|
||||
var adminHbs = hbs.create();
|
||||
helpers = rewire('../../server/helpers');
|
||||
sandbox = sinon.sandbox.create();
|
||||
apiStub = sandbox.stub(api.settings, 'read', function () {
|
||||
return when({value: 'casper'});
|
||||
@ -244,9 +245,9 @@ describe('Core Helpers', function () {
|
||||
|
||||
it('can render class string for context', function (done) {
|
||||
when.all([
|
||||
helpers.body_class.call({ghostRoot: '/'}),
|
||||
helpers.body_class.call({ghostRoot: '/a-post-title'}),
|
||||
helpers.body_class.call({ghostRoot: '/page/4'})
|
||||
helpers.body_class.call({relativeUrl: '/'}),
|
||||
helpers.body_class.call({relativeUrl: '/a-post-title'}),
|
||||
helpers.body_class.call({relativeUrl: '/page/4'})
|
||||
]).then(function (rendered) {
|
||||
rendered.length.should.equal(3);
|
||||
|
||||
@ -264,7 +265,7 @@ describe('Core Helpers', function () {
|
||||
|
||||
it('can render class for static page', function (done) {
|
||||
helpers.body_class.call({
|
||||
ghostRoot: '/',
|
||||
relativeUrl: '/',
|
||||
post: {
|
||||
page: true
|
||||
}
|
||||
@ -300,28 +301,82 @@ describe('Core Helpers', function () {
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can render page class', function (done) {
|
||||
var post = { page: true };
|
||||
|
||||
helpers.post_class.call(post).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('post page');
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ghost_head Helper', function () {
|
||||
// TODO: these tests should be easier to do!
|
||||
var configUrl = config().url;
|
||||
|
||||
afterEach(function (done) {
|
||||
config.paths.update(configUrl).then(function () {
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('has loaded ghost_head helper', function () {
|
||||
should.exist(handlebars.helpers.ghost_head);
|
||||
});
|
||||
|
||||
it('returns meta tag string', function (done) {
|
||||
helpers.ghost_head.call({version: "0.3.0"}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n<link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/">');
|
||||
config.paths.update('http://testurl.com/').then(function () {
|
||||
helpers.ghost_head.call({version: "0.3.0"}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
|
||||
'<link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/">\n' +
|
||||
'<link rel="canonical" href="http://testurl.com/" />');
|
||||
|
||||
done();
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('returns meta tag string even if version is invalid', function (done) {
|
||||
helpers.ghost_head.call({version: "0.9"}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n<link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/">');
|
||||
config.paths.update('http://testurl.com/').then(function () {
|
||||
return helpers.ghost_head.call({version: "0.9"}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n' +
|
||||
'<link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/">\n' +
|
||||
'<link rel="canonical" href="http://testurl.com/" />');
|
||||
|
||||
done();
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('returns correct rss url with subdirectory', function (done) {
|
||||
config.paths.update('http://testurl.com/blog/').then(function () {
|
||||
return helpers.ghost_head.call({version: "0.3.0"}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
|
||||
'<link rel="alternate" type="application/rss+xml" title="Ghost" href="/blog/rss/">\n' +
|
||||
'<link rel="canonical" href="http://testurl.com/blog/" />');
|
||||
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('returns canonical URL', function (done) {
|
||||
config.paths.update('http://testurl.com').then(function () {
|
||||
return helpers.ghost_head.call({version: "0.3.0", relativeUrl: '/about/'}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n' +
|
||||
'<link rel="alternate" type="application/rss+xml" title="Ghost" href="/rss/">\n' +
|
||||
'<link rel="canonical" href="http://testurl.com/about/" />');
|
||||
|
||||
done();
|
||||
});
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
@ -392,6 +447,13 @@ describe('Core Helpers', function () {
|
||||
helpers.pageUrl(2).should.equal('/page/2/');
|
||||
helpers.pageUrl(50).should.equal('/page/50/');
|
||||
});
|
||||
|
||||
it('can return a valid url with subdirectory', function () {
|
||||
sandbox.stub(config, 'paths', function () { return {'subdir': '/blog'}; });
|
||||
helpers.pageUrl(1).should.equal('/blog/');
|
||||
helpers.pageUrl(2).should.equal('/blog/page/2/');
|
||||
helpers.pageUrl(50).should.equal('/blog/page/50/');
|
||||
});
|
||||
});
|
||||
|
||||
describe("Pagination helper", function () {
|
||||
@ -565,22 +627,22 @@ describe('Core Helpers', function () {
|
||||
});
|
||||
|
||||
it('can return blog title', function (done) {
|
||||
helpers.meta_title.call({ghostRoot: '/'}).then(function (rendered) {
|
||||
helpers.meta_title.call({relativeUrl: '/'}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('Ghost');
|
||||
|
||||
done();
|
||||
}, done);
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can return title of a post', function (done) {
|
||||
var post = {ghostRoot: '/nice-post', post: {title: 'Post Title'}};
|
||||
var post = {relativeUrl: '/nice-post', post: {title: 'Post Title'}};
|
||||
helpers.meta_title.call(post).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('Post Title');
|
||||
|
||||
done();
|
||||
}, done);
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
|
||||
@ -591,22 +653,22 @@ describe('Core Helpers', function () {
|
||||
});
|
||||
|
||||
it('can return blog description', function (done) {
|
||||
helpers.meta_description.call({ghostRoot: '/'}).then(function (rendered) {
|
||||
helpers.meta_description.call({relativeUrl: '/'}).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('Just a blogging platform.');
|
||||
|
||||
done();
|
||||
}, done);
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
it('can return empty description on post', function (done) {
|
||||
var post = {ghostRoot: '/nice-post', post: {title: 'Post Title'}};
|
||||
var post = {relativeUrl: '/nice-post', post: {title: 'Post Title'}};
|
||||
helpers.meta_description.call(post).then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.equal('');
|
||||
|
||||
done();
|
||||
}, done);
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
});
|
||||
@ -722,7 +784,6 @@ describe('Core Helpers', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
// set the asset hash
|
||||
helpers = rewire('../../server/helpers');
|
||||
helpers.assetHash = 'abc';
|
||||
});
|
||||
|
||||
@ -782,4 +843,98 @@ describe('Core Helpers', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('adminUrl', function () {
|
||||
var rendered,
|
||||
configUrl = config().url;
|
||||
|
||||
afterEach(function (done) {
|
||||
config.paths.update(configUrl).then(function () {
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
|
||||
|
||||
it('should output the path to admin', function () {
|
||||
rendered = helpers.adminUrl();
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('/ghost');
|
||||
});
|
||||
|
||||
it('should output the path to admin with subdirectory', function (done) {
|
||||
config.paths.update('http://testurl.com/blog/').then(function () {
|
||||
rendered = helpers.adminUrl();
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('/blog/ghost');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should output absolute path if absolute is set', function (done) {
|
||||
// no trailing slash
|
||||
config.paths.update('http://testurl.com').then(function () {
|
||||
|
||||
rendered = helpers.adminUrl({"hash": {absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/ghost');
|
||||
|
||||
// test trailing slash
|
||||
return config.paths.update('http://testurl.com/');
|
||||
}).then(function () {
|
||||
rendered = helpers.adminUrl({"hash": {absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/ghost');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should output absolute path with subdirectory', function (done) {
|
||||
config.paths.update('http://testurl.com/blog').then(function () {
|
||||
rendered = helpers.adminUrl({"hash": {absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/blog/ghost');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should output the path to frontend if frontend is set', function () {
|
||||
rendered = helpers.adminUrl({"hash": {frontend: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('/');
|
||||
});
|
||||
|
||||
it('should output the absolute path to frontend if both are set', function (done) {
|
||||
config.paths.update('http://testurl.com').then(function () {
|
||||
|
||||
rendered = helpers.adminUrl({"hash": {frontend: true, absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/');
|
||||
|
||||
return config.paths.update('http://testurl.com/');
|
||||
}).then(function () {
|
||||
rendered = helpers.adminUrl({"hash": {frontend: true, absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should output the path to frontend with subdirectory', function (done) {
|
||||
config.paths.update('http://testurl.com/blog/').then(function () {
|
||||
|
||||
rendered = helpers.adminUrl({"hash": {frontend: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('/blog/');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should output the absolute path to frontend with subdirectory', function (done) {
|
||||
config.paths.update('http://testurl.com/blog/').then(function () {
|
||||
rendered = helpers.adminUrl({"hash": {frontend: true, absolute: true}});
|
||||
should.exist(rendered);
|
||||
rendered.should.equal('http://testurl.com/blog/');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user