mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 10:21:36 +03:00
3c19a8f014
refs https://github.com/TryGhost/Toolbox/issues/152 - Have skimmed through the test suites in hopes to find some quick performance wins to bring the runtime speed closer to the one in "main". Haven't been successful to identify major wins, cleaned up a couple of small bits. - We'll have to live with a tradeoff between maintainability/unified boot VS cost of mainitaining a fake boot process. Imo extra couple seconds of runtime is worth it.
1628 lines
56 KiB
JavaScript
1628 lines
56 KiB
JavaScript
const should = require('should');
|
|
const sinon = require('sinon');
|
|
const _ = require('lodash');
|
|
const cheerio = require('cheerio');
|
|
const testUtils = require('../../../utils');
|
|
const localUtils = require('../utils');
|
|
const configUtils = require('../../../utils/configUtils');
|
|
const urlUtils = require('../../../utils/urlUtils');
|
|
|
|
const routeSettingsService = require('../../../../core/server/services/route-settings');
|
|
const themeEngine = require('../../../../core/frontend/services/theme-engine');
|
|
|
|
describe('Integration - Web - Site canary', function () {
|
|
let app;
|
|
|
|
before(localUtils.urlService.resetGenerators);
|
|
before(testUtils.teardownDb);
|
|
before(testUtils.setup('users:roles', 'posts'));
|
|
|
|
let postSpy;
|
|
|
|
describe('default routes.yaml', function () {
|
|
before(async function () {
|
|
localUtils.defaultMocks(sinon, {amp: true});
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
before(function () {
|
|
configUtils.set('url', 'http://example.com');
|
|
urlUtils.stubUrlUtilsFromConfig();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
sinon.stub(themeEngine.getActive(), 'engine').withArgs('ghost-api').returns('canary');
|
|
sinon.stub(themeEngine.getActive(), 'config').withArgs('posts_per_page').returns(2);
|
|
const postsAPI = require('../../../../core/server/api/canary/posts-public');
|
|
postSpy = sinon.spy(postsAPI.browse, 'query');
|
|
});
|
|
|
|
afterEach(function () {
|
|
postSpy.restore();
|
|
sinon.restore();
|
|
});
|
|
|
|
after(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
sinon.restore();
|
|
});
|
|
|
|
describe('behaviour: default cases', function () {
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('post');
|
|
});
|
|
});
|
|
|
|
it('serve amp', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/amp/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.match(/amp\.hbs/);
|
|
response.body.should.match(/<h1>HTML Ipsum Presents<\/h1>/);
|
|
});
|
|
});
|
|
|
|
it('post not found', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/not-found/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('serve static page', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/static-page-test/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('page');
|
|
});
|
|
});
|
|
|
|
it('serve author', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/author/joe-bloggs/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('author');
|
|
|
|
$('.author-bio').length.should.equal(1);
|
|
});
|
|
});
|
|
|
|
it('serve tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/tag/bacon/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('tag');
|
|
|
|
postSpy.args[0][0].options.filter.should.eql('(tags:\'bacon\'+tags.visibility:public)+type:post');
|
|
postSpy.args[0][0].options.page.should.eql(1);
|
|
postSpy.args[0][0].options.limit.should.eql(2);
|
|
});
|
|
});
|
|
|
|
it('serve tag rss', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/tag/bacon/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve collection', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(2);
|
|
|
|
should.exist(response.res.locals.context);
|
|
should.exist(response.res.locals.version);
|
|
should.exist(response.res.locals.safeVersion);
|
|
should.exist(response.res.locals.safeVersion);
|
|
should.exist(response.res.locals.relativeUrl);
|
|
should.exist(response.res.locals.secure);
|
|
should.exist(response.res.routerOptions);
|
|
});
|
|
});
|
|
|
|
it('serve collection: page 2', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/page/2/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(2);
|
|
});
|
|
});
|
|
|
|
it('serve theme asset', function () {
|
|
//configUtils.set('url', 'https://example.com');
|
|
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/assets/css/screen.css',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('behaviour: prettify', function () {
|
|
it('url without slash', function () {
|
|
const req = {
|
|
secure: false,
|
|
method: 'GET',
|
|
url: '/prettify-me',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('/prettify-me/');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('behaviour: url redirects', function () {
|
|
describe('pagination', function () {
|
|
it('redirect /page/1/ to /', function () {
|
|
const req = {
|
|
secure: false,
|
|
host: 'example.com',
|
|
method: 'GET',
|
|
url: '/page/1/'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('/');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('rss', function () {
|
|
it('redirect /feed/ to /rss/', function () {
|
|
const req = {
|
|
secure: false,
|
|
host: 'example.com',
|
|
method: 'GET',
|
|
url: '/feed/'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('/rss/');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('https', function () {
|
|
before(function () {
|
|
configUtils.set('url', 'https://example.com');
|
|
urlUtils.stubUrlUtilsFromConfig();
|
|
});
|
|
|
|
after(function () {
|
|
urlUtils.restore();
|
|
configUtils.restore();
|
|
});
|
|
|
|
describe('protocol', function () {
|
|
it('blog is https, request is http', function () {
|
|
const req = {
|
|
secure: false,
|
|
host: 'example.com',
|
|
method: 'GET',
|
|
url: '/html-ipsum'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('https://example.com/html-ipsum/');
|
|
});
|
|
});
|
|
|
|
it('blog is https, request is http, trailing slash exists already', function () {
|
|
const req = {
|
|
secure: false,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('https://example.com/html-ipsum/');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('assets', function () {
|
|
it('blog is https, request is http', function () {
|
|
const req = {
|
|
secure: false,
|
|
method: 'GET',
|
|
url: '/favicon.png',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('https://example.com/favicon.png');
|
|
});
|
|
});
|
|
|
|
it('blog is https, request is http', function () {
|
|
const req = {
|
|
secure: false,
|
|
method: 'GET',
|
|
url: '/assets/css/main.css',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('https://example.com/assets/css/main.css');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('extended routes.yaml: collections', function () {
|
|
describe('2 collections', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {
|
|
'/': {templates: ['home']}
|
|
},
|
|
|
|
collections: {
|
|
'/podcast/': {
|
|
permalink: '/podcast/:slug/',
|
|
filter: 'featured:true'
|
|
},
|
|
|
|
'/something/': {
|
|
permalink: '/something/:slug/',
|
|
filter: 'featured:false'
|
|
}
|
|
},
|
|
|
|
taxonomies: {
|
|
tag: '/categories/:slug/',
|
|
author: '/authors/:slug/'
|
|
}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon, {theme: 'test-theme'});
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve static route', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('home');
|
|
});
|
|
});
|
|
|
|
it('serve rss', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/podcast/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/something/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('post');
|
|
});
|
|
});
|
|
|
|
it('serve collection: podcast with default template', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/podcast/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(2);
|
|
});
|
|
});
|
|
|
|
it('serve collection: something with custom template', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/something/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('something');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('no collections', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {
|
|
'/something/': {
|
|
templates: ['something']
|
|
}
|
|
},
|
|
collections: {},
|
|
taxonomies: {}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon, {theme: 'test-theme'});
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve route', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/something/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('something');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('static permalink route', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/podcast/': {
|
|
permalink: '/featured/',
|
|
filter: 'featured:true'
|
|
},
|
|
|
|
'/': {
|
|
permalink: '/:slug/'
|
|
}
|
|
},
|
|
|
|
taxonomies: {}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/featured/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
// We can't find a post with the slug "featured"
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('post');
|
|
});
|
|
});
|
|
|
|
it('serve author', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/author/joe-bloggs/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('serve tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/tag/bacon/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('primary author permalink', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/something/': {
|
|
permalink: '/:primary_author/:slug/'
|
|
}
|
|
},
|
|
|
|
taxonomies: {}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/joe-bloggs/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('post');
|
|
});
|
|
});
|
|
|
|
it('post without author', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('page', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/static-page-test/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('page');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('primary tag permalink', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/something/': {
|
|
permalink: '/something/:primary_tag/:slug/'
|
|
}
|
|
},
|
|
|
|
taxonomies: {}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve post', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/something/kitchen-sink/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('post');
|
|
});
|
|
});
|
|
|
|
it('post without tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/something/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('post without tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
response.template.should.eql('error-404');
|
|
});
|
|
});
|
|
|
|
it('page', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/static-page-test/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('page');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('collection/routes with data key', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {
|
|
'/my-page/': {
|
|
data: {
|
|
query: {
|
|
page: {
|
|
controller: 'pagesPublic',
|
|
resource: 'pages',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'static-page-test'
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
pages: [{redirect: true, slug: 'static-page-test'}]
|
|
}
|
|
},
|
|
templates: ['page']
|
|
}
|
|
},
|
|
|
|
collections: {
|
|
'/food/': {
|
|
permalink: '/food/:slug/',
|
|
filter: 'tag:bacon+tag:-chorizo',
|
|
data: {
|
|
query: {
|
|
tag: {
|
|
controller: 'tagsPublic',
|
|
resource: 'tags',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'bacon'
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
tags: [{redirect: true, slug: 'bacon'}]
|
|
}
|
|
}
|
|
},
|
|
'/sport/': {
|
|
permalink: '/sport/:slug/',
|
|
filter: 'tag:chorizo+tag:-bacon',
|
|
data: {
|
|
query: {
|
|
apollo: {
|
|
controller: 'tagsPublic',
|
|
resource: 'tags',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'chorizo'
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
tags: [{redirect: false, slug: 'chorizo'}]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
taxonomies: {
|
|
tag: '/categories/:slug/',
|
|
author: '/authors/:slug/'
|
|
}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve /food/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/food/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
});
|
|
});
|
|
|
|
it('serve bacon tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/categories/bacon/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
});
|
|
});
|
|
|
|
it('serve /sport/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/sport/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
});
|
|
});
|
|
|
|
it('serve chorizo tag', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/categories/chorizo/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve my-page', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/my-page/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('extended routes.yaml: templates', function () {
|
|
describe('default template, no template', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/': {
|
|
permalink: '/:slug/',
|
|
templates: ['default']
|
|
},
|
|
'/magic/': {
|
|
permalink: '/magic/:slug/'
|
|
}
|
|
}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve collection', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('default');
|
|
});
|
|
});
|
|
|
|
it('serve second collectiom', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/magic/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('two templates', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/': {
|
|
permalink: '/:slug/',
|
|
templates: ['something', 'default']
|
|
}
|
|
}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon);
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve collection', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('default');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('home.hbs priority', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {},
|
|
|
|
collections: {
|
|
'/': {
|
|
permalink: '/:slug/',
|
|
templates: ['something', 'default']
|
|
},
|
|
'/magic/': {
|
|
permalink: '/magic/:slug/',
|
|
templates: ['something', 'default']
|
|
}
|
|
}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon, {theme: 'test-theme'});
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve collection', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('home');
|
|
});
|
|
});
|
|
|
|
it('serve second page collection: should use index.hbs', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/magic/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('something');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('extended routes.yaml: routes', function () {
|
|
describe('channels', function () {
|
|
before(localUtils.urlService.resetGenerators);
|
|
before(testUtils.teardownDb);
|
|
before(testUtils.setup('users:roles', 'posts'));
|
|
|
|
before(async function () {
|
|
localUtils.defaultMocks(sinon, {theme: 'test-theme-channels'});
|
|
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {
|
|
'/channel1/': {
|
|
controller: 'channel',
|
|
filter: 'tag:kitchen-sink',
|
|
data: {
|
|
query: {
|
|
tag: {
|
|
controller: 'tagsPublic',
|
|
resource: 'tags',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'kitchen-sink'
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
tags: [{redirect: true, slug: 'kitchen-sink'}]
|
|
}
|
|
}
|
|
},
|
|
|
|
'/channel2/': {
|
|
controller: 'channel',
|
|
filter: 'tag:bacon',
|
|
data: {
|
|
query: {
|
|
tag: {
|
|
controller: 'tagsPublic',
|
|
resource: 'tags',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'bacon'
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
tags: [{redirect: true, slug: 'bacon'}]
|
|
}
|
|
},
|
|
templates: ['default']
|
|
},
|
|
|
|
'/channel3/': {
|
|
controller: 'channel',
|
|
filter: 'author:joe-bloggs',
|
|
data: {
|
|
query: {
|
|
joe: {
|
|
controller: 'authorsPublic',
|
|
resource: 'authors',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'joe-bloggs',
|
|
redirect: false
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
authors: [{redirect: false, slug: 'joe-bloggs'}]
|
|
}
|
|
}
|
|
},
|
|
|
|
'/channel4/': {
|
|
controller: 'channel',
|
|
filter: 'author:joe-bloggs'
|
|
},
|
|
|
|
'/channel5/': {
|
|
controller: 'channel',
|
|
data: {
|
|
query: {
|
|
tag: {
|
|
controller: 'authorsPublic',
|
|
resource: 'authors',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'joe-bloggs',
|
|
redirect: false
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
authors: [{redirect: false, slug: 'joe-bloggs'}]
|
|
}
|
|
}
|
|
},
|
|
|
|
'/channel6/': {
|
|
controller: 'channel',
|
|
data: {
|
|
query: {
|
|
post: {
|
|
controller: 'postsPublic',
|
|
resource: 'posts',
|
|
type: 'read',
|
|
options: {
|
|
slug: 'html-ipsum',
|
|
redirect: true
|
|
}
|
|
}
|
|
},
|
|
router: {
|
|
posts: [{redirect: true, slug: 'html-ipsum'}]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
collections: {
|
|
'/': {
|
|
permalink: '/:slug/'
|
|
}
|
|
},
|
|
|
|
taxonomies: {
|
|
tag: '/tag/:slug/',
|
|
author: '/author/:slug/'
|
|
}
|
|
}));
|
|
|
|
app = await localUtils.initGhost();
|
|
sinon.stub(themeEngine.getActive(), 'config').withArgs('posts_per_page').returns(10);
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve channel 1', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel1/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(2);
|
|
});
|
|
});
|
|
|
|
it('serve channel 1: rss', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel1/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.headers['content-type'].should.eql('text/xml; charset=UTF-8');
|
|
});
|
|
});
|
|
|
|
it('serve channel 2', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel2/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('default');
|
|
|
|
// default template does not list posts
|
|
$('.post-card').length.should.equal(0);
|
|
});
|
|
});
|
|
|
|
it('serve channel 3', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel3/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('channel3');
|
|
});
|
|
});
|
|
|
|
it('serve channel 4', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel4/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(4);
|
|
});
|
|
});
|
|
|
|
it('serve channel 5', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel5/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(10);
|
|
});
|
|
});
|
|
|
|
it('serve channel 6', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/channel6/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('index');
|
|
|
|
$('.post-card').length.should.equal(10);
|
|
});
|
|
});
|
|
|
|
it('serve kitching-sink: redirect', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/tag/kitchen-sink/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('/channel1/');
|
|
});
|
|
});
|
|
|
|
it('serve html-ipsum: redirect', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/html-ipsum/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(301);
|
|
response.headers.location.should.eql('/channel6/');
|
|
});
|
|
});
|
|
|
|
it('serve chorizo: no redirect', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/tag/chorizo/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve joe-bloggs', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/author/joe-bloggs/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('extended routes.yaml (5): rss override', function () {
|
|
before(async function () {
|
|
sinon.stub(routeSettingsService, 'loadRouteSettings').get(() => () => ({
|
|
routes: {
|
|
'/podcast/rss/': {
|
|
templates: ['podcast/rss'],
|
|
content_type: 'text/xml'
|
|
},
|
|
'/cooking/': {
|
|
controller: 'channel',
|
|
rss: false
|
|
},
|
|
'/flat/': {
|
|
controller: 'channel'
|
|
}
|
|
},
|
|
|
|
collections: {
|
|
'/podcast/': {
|
|
permalink: '/:slug/',
|
|
filter: 'featured:true',
|
|
templates: ['home'],
|
|
rss: false
|
|
},
|
|
'/music/': {
|
|
permalink: '/:slug/',
|
|
rss: false
|
|
},
|
|
'/': {
|
|
permalink: '/:slug/'
|
|
}
|
|
},
|
|
|
|
taxonomies: {}
|
|
}));
|
|
|
|
localUtils.urlService.resetGenerators();
|
|
localUtils.defaultMocks(sinon, {theme: 'test-theme'});
|
|
|
|
app = await localUtils.initGhost();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
localUtils.overrideGhostConfig(configUtils);
|
|
});
|
|
|
|
afterEach(function () {
|
|
configUtils.restore();
|
|
urlUtils.restore();
|
|
});
|
|
|
|
after(function () {
|
|
sinon.restore();
|
|
});
|
|
|
|
it('serve /rss/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve /music/rss/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/music/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
});
|
|
});
|
|
|
|
it('serve /cooking/rss/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/cooking/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(404);
|
|
});
|
|
});
|
|
|
|
it('serve /flat/rss/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/flat/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
});
|
|
});
|
|
|
|
it('serve /podcast/rss/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/podcast/rss/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
response.statusCode.should.eql(200);
|
|
response.template.should.eql('podcast/rss');
|
|
response.headers['content-type'].should.eql('text/xml; charset=utf-8');
|
|
response.body.match(/<link>/g).length.should.eql(2);
|
|
});
|
|
});
|
|
|
|
it('serve /podcast/', function () {
|
|
const req = {
|
|
secure: true,
|
|
method: 'GET',
|
|
url: '/podcast/',
|
|
host: 'example.com'
|
|
};
|
|
|
|
return localUtils.mockExpress.invoke(app, req)
|
|
.then(function (response) {
|
|
const $ = cheerio.load(response.body);
|
|
response.statusCode.should.eql(200);
|
|
$('head link')[1].attribs.href.should.eql('https://127.0.0.1:2369/rss/');
|
|
});
|
|
});
|
|
});
|
|
});
|