mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
🔥 Removed V1 code/references in frontend resources/routing layer (#11087)
no issue - Removed v1 'author' leftover in include statement for preview controller - Removed v1 'author' leftover in include statement for preview controller - Removed v1 'author' leftover in include statement in entry lookup routing helper - Migrated related test to use v2 API controller - Removed v0.1 routing confif - Removed v0.1 url config - Fixed tests that had to do with url's in resources after removing v0.1 resources from URL cache - Removed v1 'author' leftover in include statement in static routing helper - Modified the test to use v2 API - Removed v1 specific condition with 'page' in context helper - Fixed dynamic routing spec after theme switch to v2. All tested users have to have at least one published post to be shown as an author - Fixed URL Service spec to use theme engine v2
This commit is contained in:
parent
a9050f68ea
commit
7dc38e2078
20 changed files with 143 additions and 2964 deletions
|
@ -1,70 +0,0 @@
|
|||
/* eslint-disable */
|
||||
module.exports.QUERY = {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
type: 'read',
|
||||
resource: 'tags',
|
||||
options: {
|
||||
slug: '%s',
|
||||
visibility: 'public'
|
||||
}
|
||||
},
|
||||
author: {
|
||||
resourceAlias: 'authors',
|
||||
controller: 'users',
|
||||
type: 'read',
|
||||
resource: 'users',
|
||||
options: {
|
||||
slug: '%s',
|
||||
visibility: 'public'
|
||||
}
|
||||
},
|
||||
user: {
|
||||
resourceAlias: 'authors',
|
||||
controller: 'users',
|
||||
type: 'read',
|
||||
resource: 'users',
|
||||
options: {
|
||||
slug: '%s',
|
||||
visibility: 'public'
|
||||
}
|
||||
},
|
||||
post: {
|
||||
controller: 'posts',
|
||||
type: 'read',
|
||||
resource: 'posts',
|
||||
options: {
|
||||
slug: '%s',
|
||||
status: 'published',
|
||||
page: 0
|
||||
}
|
||||
},
|
||||
page: {
|
||||
controller: 'posts',
|
||||
type: 'read',
|
||||
resource: 'posts',
|
||||
options: {
|
||||
slug: '%s',
|
||||
status: 'published',
|
||||
page: 1
|
||||
}
|
||||
},
|
||||
preview: {
|
||||
controller: 'posts',
|
||||
resource: 'posts'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.TAXONOMIES = {
|
||||
tag: {
|
||||
filter: 'tags:\'%s\'+tags.visibility:public',
|
||||
editRedirect: '#/settings/tags/:slug/',
|
||||
resource: 'tags'
|
||||
},
|
||||
author: {
|
||||
filter: 'authors:\'%s\'',
|
||||
editRedirect: '#/team/:slug/',
|
||||
resource: 'authors'
|
||||
}
|
||||
};
|
||||
/* eslint-enable */
|
|
@ -67,13 +67,6 @@ module.exports = function entryController(req, res, next) {
|
|||
* @NOTE:
|
||||
*
|
||||
* Ensure we redirect to the correct post url including subdirectory.
|
||||
*
|
||||
* @NOTE:
|
||||
* Keep in mind, that the logic here is used for v0.1 and v2.
|
||||
* v0.1 returns relative urls, v2 returns absolute urls.
|
||||
*
|
||||
* @TODO:
|
||||
* Simplify if we drop v0.1.
|
||||
*/
|
||||
if (urlUtils.absoluteToRelative(entry.url, {withoutSubdirectory: true}) !== req.path) {
|
||||
debug('redirect');
|
||||
|
|
|
@ -18,8 +18,7 @@ module.exports = function previewController(req, res, next) {
|
|||
const params = {
|
||||
uuid: req.params.uuid,
|
||||
status: 'all',
|
||||
// @TODO: Remove "author" if we drop v0.1
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
};
|
||||
|
||||
return api[res.routerOptions.query.controller]
|
||||
|
|
|
@ -14,8 +14,7 @@ function processQuery(query, locals) {
|
|||
// We override the `include` property for now, because the full data set is required anyway.
|
||||
if (_.get(query, 'resource') === 'posts') {
|
||||
_.extend(query.options, {
|
||||
// @TODO: Remove "author" when we drop v0.1
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ function setResponseContext(req, res, data) {
|
|||
}
|
||||
|
||||
// Add context 'amp' to either post or page, if we have an `*/amp` route
|
||||
if (ampPattern.test(res.locals.relativeUrl) && data.post) {
|
||||
if (ampPattern.test(res.locals.relativeUrl) && (data.post || data.page)) {
|
||||
res.locals.context.push('amp');
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,7 @@ function setResponseContext(req, res, data) {
|
|||
}
|
||||
}
|
||||
|
||||
// @TODO: remove first if condition when we drop v0.1
|
||||
if (data && data.post && data.post.page) {
|
||||
if (!res.locals.context.includes('page')) {
|
||||
res.locals.context.push('page');
|
||||
}
|
||||
} else if (data && data.post) {
|
||||
if (data && data.post) {
|
||||
if (!res.locals.context.includes('post')) {
|
||||
res.locals.context.push('post');
|
||||
}
|
||||
|
|
|
@ -40,11 +40,7 @@ function entryLookup(postUrl, routerOptions, locals) {
|
|||
}
|
||||
|
||||
let options = {
|
||||
/**
|
||||
* @deprecated: `author`, will be removed in Ghost 3.0
|
||||
* @TODO: Remove "author" when we drop v0.1
|
||||
*/
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
};
|
||||
|
||||
if (config.get('enableDeveloperExperiments')) {
|
||||
|
|
|
@ -7,7 +7,7 @@ const Promise = require('bluebird');
|
|||
const config = require('../../../../server/config');
|
||||
|
||||
// The default settings for a default post query
|
||||
// @TODO: get rid of this config and use v0.1 or v2 config
|
||||
// @TODO: get rid of this config and use v2, v3 config
|
||||
const queryDefaults = {
|
||||
type: 'browse',
|
||||
resource: 'posts',
|
||||
|
@ -22,9 +22,8 @@ const defaultQueryOptions = {
|
|||
options: {
|
||||
/**
|
||||
* @deprecated: `author`, will be removed in Ghost 3.0
|
||||
* @TODO: Remove "author" when we drop v0.1
|
||||
*/
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* These are the default resources and filters.
|
||||
* They contain minimum filters for public accessibility of resources.
|
||||
*/
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
type: 'posts',
|
||||
modelOptions: {
|
||||
modelName: 'Post',
|
||||
filter: 'visibility:public+status:published+page:false',
|
||||
exclude: [
|
||||
'title',
|
||||
'mobiledoc',
|
||||
'html',
|
||||
'plaintext',
|
||||
'amp',
|
||||
'codeinjection_head',
|
||||
'codeinjection_foot',
|
||||
'meta_title',
|
||||
'meta_description',
|
||||
'custom_excerpt',
|
||||
'og_image',
|
||||
'og_title',
|
||||
'og_description',
|
||||
'twitter_image',
|
||||
'twitter_title',
|
||||
'twitter_description',
|
||||
'custom_template',
|
||||
'locale'
|
||||
],
|
||||
withRelated: ['tags', 'authors'],
|
||||
withRelatedPrimary: {
|
||||
primary_tag: 'tags',
|
||||
primary_author: 'authors'
|
||||
},
|
||||
withRelatedFields: {
|
||||
tags: ['tags.id', 'tags.slug'],
|
||||
authors: ['users.id', 'users.slug']
|
||||
}
|
||||
},
|
||||
events: {
|
||||
add: 'post.published',
|
||||
update: 'post.published.edited',
|
||||
remove: 'post.unpublished'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'pages',
|
||||
modelOptions: {
|
||||
modelName: 'Post',
|
||||
exclude: [
|
||||
'title',
|
||||
'mobiledoc',
|
||||
'html',
|
||||
'plaintext',
|
||||
'amp',
|
||||
'codeinjection_head',
|
||||
'codeinjection_foot',
|
||||
'meta_title',
|
||||
'meta_description',
|
||||
'custom_excerpt',
|
||||
'og_image',
|
||||
'og_title',
|
||||
'og_description',
|
||||
'twitter_image',
|
||||
'twitter_title',
|
||||
'twitter_description',
|
||||
'custom_template',
|
||||
'locale',
|
||||
'tags',
|
||||
'authors',
|
||||
'primary_tag',
|
||||
'primary_author'
|
||||
],
|
||||
filter: 'visibility:public+status:published+page:true'
|
||||
},
|
||||
events: {
|
||||
add: 'page.published',
|
||||
update: 'page.published.edited',
|
||||
remove: 'page.unpublished'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'tags',
|
||||
keep: ['id', 'slug', 'updated_at', 'created_at'],
|
||||
modelOptions: {
|
||||
modelName: 'Tag',
|
||||
exclude: ['description', 'meta_title', 'meta_description'],
|
||||
filter: 'visibility:public'
|
||||
},
|
||||
events: {
|
||||
add: 'tag.added',
|
||||
update: 'tag.edited',
|
||||
remove: 'tag.deleted'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'authors',
|
||||
modelOptions: {
|
||||
modelName: 'User',
|
||||
exclude: [
|
||||
'bio',
|
||||
'website',
|
||||
'location',
|
||||
'facebook',
|
||||
'twitter',
|
||||
'accessibility',
|
||||
'meta_title',
|
||||
'meta_description',
|
||||
'tour'
|
||||
],
|
||||
filter: 'visibility:public'
|
||||
},
|
||||
events: {
|
||||
add: 'user.activated',
|
||||
update: 'user.activated.edited',
|
||||
remove: 'user.deleted'
|
||||
}
|
||||
}
|
||||
];
|
|
@ -43,7 +43,9 @@ describe('Tag API', function () {
|
|||
jsonResponse.meta.pagination.should.have.property('next', null);
|
||||
jsonResponse.meta.pagination.should.have.property('prev', null);
|
||||
|
||||
jsonResponse.tags[0].url.should.eql(`${config.get('url')}/tag/pollo/`);
|
||||
// returns 404 because this tag has no published posts
|
||||
jsonResponse.tags[0].url.should.eql(`${config.get('url')}/404/`);
|
||||
jsonResponse.tags[1].url.should.eql(`${config.get('url')}/tag/kitchen-sink/`);
|
||||
|
||||
should.exist(jsonResponse.tags[0].count.posts);
|
||||
});
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
const should = require('should');
|
||||
const _ = require('lodash');
|
||||
const supertest = require('supertest');
|
||||
const moment = require('moment');
|
||||
const Promise = require('bluebird');
|
||||
const ObjectId = require('bson-objectid');
|
||||
const testUtils = require('../../../utils');
|
||||
const localUtils = require('./utils');
|
||||
const config = require('../../../../server/config');
|
||||
|
@ -13,12 +11,11 @@ const ghost = testUtils.startGhost;
|
|||
let request;
|
||||
|
||||
describe('User API', function () {
|
||||
let ghostServer, inactiveUser, admin;
|
||||
let inactiveUser, admin;
|
||||
|
||||
before(function () {
|
||||
return ghost()
|
||||
.then(function (_ghostServer) {
|
||||
ghostServer = _ghostServer;
|
||||
.then(function () {
|
||||
request = supertest.agent(config.get('url'));
|
||||
})
|
||||
.then(function () {
|
||||
|
@ -82,10 +79,11 @@ describe('User API', function () {
|
|||
testUtils.API.isISO8601(jsonResponse.users[3].created_at).should.be.true();
|
||||
testUtils.API.isISO8601(jsonResponse.users[3].updated_at).should.be.true();
|
||||
|
||||
jsonResponse.users[0].url.should.eql(`${config.get('url')}/author/admin-user/`);
|
||||
// only "ghost" author has a published post
|
||||
jsonResponse.users[0].url.should.eql(`${config.get('url')}/404/`);
|
||||
jsonResponse.users[1].url.should.eql(`${config.get('url')}/404/`);
|
||||
jsonResponse.users[2].url.should.eql(`${config.get('url')}/author/ghost/`);
|
||||
jsonResponse.users[3].url.should.eql(`${config.get('url')}/author/joe-bloggs/`);
|
||||
jsonResponse.users[3].url.should.eql(`${config.get('url')}/404/`);
|
||||
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@ describe('Integration: services/url/UrlService', function () {
|
|||
models.init();
|
||||
|
||||
sinon.stub(themes, 'getActive').returns({
|
||||
engine: () => 'v0.1'
|
||||
engine: () => 'v2'
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -148,11 +148,11 @@ describe('Integration: services/url/UrlService', function () {
|
|||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'tags') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
generator.getUrls().length.should.eql(3);
|
||||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'authors') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
generator.getUrls().length.should.eql(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -175,25 +175,22 @@ describe('Integration: services/url/UrlService', function () {
|
|||
url.should.eql('/tag/chorizo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[3].id);
|
||||
url.should.eql('/tag/pollo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[4].id);
|
||||
url.should.eql('/tag/injection/');
|
||||
url.should.eql('/404/'); // tags with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[0].id);
|
||||
url.should.eql('/author/joe-bloggs/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[1].id);
|
||||
url.should.eql('/author/smith-wellingsworth/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[2].id);
|
||||
url.should.eql('/author/jimothy-bogendath/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[3].id);
|
||||
url.should.eql('/author/slimer-mcectoplasm/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[4].id);
|
||||
url.should.eql('/author/contributor/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
});
|
||||
|
||||
it('getResource', function () {
|
||||
|
@ -356,11 +353,11 @@ describe('Integration: services/url/UrlService', function () {
|
|||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'tags') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
generator.getUrls().length.should.eql(3);
|
||||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'authors') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
generator.getUrls().length.should.eql(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -384,25 +381,22 @@ describe('Integration: services/url/UrlService', function () {
|
|||
url.should.eql('/category/chorizo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[3].id);
|
||||
url.should.eql('/category/pollo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[4].id);
|
||||
url.should.eql('/category/injection/');
|
||||
url.should.eql('/404/'); // tags with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[0].id);
|
||||
url.should.eql('/persons/joe-bloggs/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[1].id);
|
||||
url.should.eql('/persons/smith-wellingsworth/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[2].id);
|
||||
url.should.eql('/persons/jimothy-bogendath/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[3].id);
|
||||
url.should.eql('/persons/slimer-mcectoplasm/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[4].id);
|
||||
url.should.eql('/persons/contributor/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -553,11 +547,11 @@ describe('Integration: services/url/UrlService', function () {
|
|||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'tags') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
generator.getUrls().length.should.eql(3);
|
||||
}
|
||||
|
||||
if (generator.router.getResourceType() === 'users') {
|
||||
generator.getUrls().length.should.eql(5);
|
||||
if (generator.router.getResourceType() === 'authors') {
|
||||
generator.getUrls().length.should.eql(2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -581,25 +575,22 @@ describe('Integration: services/url/UrlService', function () {
|
|||
url.should.eql('/category/chorizo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[3].id);
|
||||
url.should.eql('/category/pollo/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.tags[4].id);
|
||||
url.should.eql('/category/injection/');
|
||||
url.should.eql('/404/'); // tags with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[0].id);
|
||||
url.should.eql('/persons/joe-bloggs/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[1].id);
|
||||
url.should.eql('/persons/smith-wellingsworth/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[2].id);
|
||||
url.should.eql('/persons/jimothy-bogendath/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[3].id);
|
||||
url.should.eql('/persons/slimer-mcectoplasm/');
|
||||
|
||||
url = urlService.getUrlByResourceId(testUtils.DataGenerator.forKnex.users[4].id);
|
||||
url.should.eql('/persons/contributor/');
|
||||
url.should.eql('/404/'); // users with no posts should not be public
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -394,10 +394,28 @@ describe('Dynamic Routing', function () {
|
|||
return testUtils.initData();
|
||||
}).then(function () {
|
||||
return testUtils.fixtures.overrideOwnerUser(ownerSlug);
|
||||
}).then(function (insertedUser) {
|
||||
return testUtils.fixtures.insertPosts([
|
||||
testUtils.DataGenerator.forKnex.createPost({
|
||||
author_id: insertedUser.id
|
||||
})
|
||||
]);
|
||||
}).then(function () {
|
||||
return testUtils.fixtures.insertOneUser(lockedUser);
|
||||
}).then(function () {
|
||||
}).then(function (insertedUser) {
|
||||
return testUtils.fixtures.insertPosts([
|
||||
testUtils.DataGenerator.forKnex.createPost({
|
||||
author_id: insertedUser.id
|
||||
})
|
||||
]);
|
||||
}).then(() => {
|
||||
return testUtils.fixtures.insertOneUser(suspendedUser);
|
||||
}).then(function (insertedUser) {
|
||||
return testUtils.fixtures.insertPosts([
|
||||
testUtils.DataGenerator.forKnex.createPost({
|
||||
author_id: insertedUser.id
|
||||
})
|
||||
]);
|
||||
}).then(function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,119 +27,6 @@ describe('Unit - services/routing/controllers/preview', function () {
|
|||
configUtils.restore();
|
||||
});
|
||||
|
||||
describe('v0.1', function () {
|
||||
beforeEach(function () {
|
||||
post = testUtils.DataGenerator.forKnex.createPost({status: 'draft'});
|
||||
|
||||
apiResponse = {
|
||||
posts: [post]
|
||||
};
|
||||
|
||||
req = {
|
||||
path: '/',
|
||||
params: {
|
||||
uuid: 'something'
|
||||
},
|
||||
route: {}
|
||||
};
|
||||
|
||||
res = {
|
||||
routerOptions: {
|
||||
query: {controller: 'posts', resource: 'posts'}
|
||||
},
|
||||
locals: {
|
||||
apiVersion: 'v0.1'
|
||||
},
|
||||
render: sinon.spy(),
|
||||
redirect: sinon.spy(),
|
||||
set: sinon.spy()
|
||||
};
|
||||
|
||||
secureStub = sinon.stub();
|
||||
|
||||
sinon.stub(urlUtils, 'redirectToAdmin');
|
||||
sinon.stub(urlUtils, 'redirect301');
|
||||
sinon.stub(urlService, 'getUrlByResourceId');
|
||||
|
||||
sinon.stub(helpers, 'secure').get(function () {
|
||||
return secureStub;
|
||||
});
|
||||
|
||||
renderStub = sinon.stub();
|
||||
sinon.stub(helpers, 'renderEntry').get(function () {
|
||||
return function () {
|
||||
return renderStub;
|
||||
};
|
||||
});
|
||||
|
||||
sinon.stub(api.posts, 'read').withArgs({
|
||||
uuid: req.params.uuid,
|
||||
status: 'all',
|
||||
include: 'author,authors,tags'
|
||||
}).callsFake(function () {
|
||||
return Promise.resolve(apiResponse);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render post', function (done) {
|
||||
controllers.preview(req, res, failTest(done)).then(function () {
|
||||
secureStub.called.should.be.true();
|
||||
renderStub.called.should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('should call next if post is not found', function (done) {
|
||||
apiResponse = {posts: []};
|
||||
|
||||
controllers.preview(req, res, function (err) {
|
||||
should.not.exist(err);
|
||||
renderStub.called.should.be.false();
|
||||
secureStub.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call redirect if post is published', function (done) {
|
||||
post.status = 'published';
|
||||
urlService.getUrlByResourceId.withArgs(post.id).returns('/something/');
|
||||
|
||||
urlUtils.redirect301.callsFake(function (res, postUrl) {
|
||||
postUrl.should.eql('/something/');
|
||||
renderStub.called.should.be.false();
|
||||
secureStub.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
|
||||
controllers.preview(req, res, failTest(done));
|
||||
});
|
||||
|
||||
it('should call redirect if /edit/ (options param) is detected', function (done) {
|
||||
req.params.options = 'edit';
|
||||
|
||||
urlUtils.redirectToAdmin.callsFake(function (statusCode, res, editorUrl) {
|
||||
statusCode.should.eql(302);
|
||||
editorUrl.should.eql(EDITOR_URL + post.id);
|
||||
renderStub.called.should.be.false();
|
||||
secureStub.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
|
||||
controllers.preview(req, res, failTest(done));
|
||||
});
|
||||
|
||||
it('should call next for unknown options param detected', function (done) {
|
||||
req.params.options = 'abcde';
|
||||
|
||||
controllers.preview(req, res, function (err) {
|
||||
should.not.exist(err);
|
||||
renderStub.called.should.be.false();
|
||||
secureStub.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('v2', function () {
|
||||
let previewStub;
|
||||
|
||||
|
@ -191,7 +78,7 @@ describe('Unit - services/routing/controllers/preview', function () {
|
|||
previewStub.withArgs({
|
||||
uuid: req.params.uuid,
|
||||
status: 'all',
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
}).resolves(apiResponse);
|
||||
|
||||
sinon.stub(api.v2, 'preview').get(() => {
|
||||
|
@ -261,7 +148,7 @@ describe('Unit - services/routing/controllers/preview', function () {
|
|||
previewStub.withArgs({
|
||||
uuid: req.params.uuid,
|
||||
status: 'all',
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
}).resolves(apiResponse);
|
||||
|
||||
sinon.stub(api.canary, 'preview').get(() => {
|
||||
|
@ -331,7 +218,7 @@ describe('Unit - services/routing/controllers/preview', function () {
|
|||
previewStub.withArgs({
|
||||
uuid: req.params.uuid,
|
||||
status: 'all',
|
||||
include: 'author,authors,tags'
|
||||
include: 'authors,tags'
|
||||
}).resolves(apiResponse);
|
||||
|
||||
sinon.stub(api.v3, 'preview').get(() => {
|
||||
|
|
|
@ -14,22 +14,30 @@ function failTest(done) {
|
|||
}
|
||||
|
||||
describe('Unit - services/routing/controllers/static', function () {
|
||||
let req, res, secureStub, renderStub, handleErrorStub, formatResponseStub, posts, postsPerPage;
|
||||
let req,
|
||||
res,
|
||||
secureStub,
|
||||
renderStub,
|
||||
handleErrorStub,
|
||||
formatResponseStub,
|
||||
postsPerPage,
|
||||
tagsReadStub;
|
||||
|
||||
beforeEach(function () {
|
||||
postsPerPage = 5;
|
||||
|
||||
posts = [
|
||||
testUtils.DataGenerator.forKnex.createPost()
|
||||
];
|
||||
|
||||
secureStub = sinon.stub();
|
||||
renderStub = sinon.stub();
|
||||
handleErrorStub = sinon.stub();
|
||||
formatResponseStub = sinon.stub();
|
||||
formatResponseStub.entries = sinon.stub();
|
||||
|
||||
sinon.stub(api.tags, 'read');
|
||||
tagsReadStub = sinon.stub().resolves();
|
||||
sinon.stub(api.v2, 'tagsPublic').get(() => {
|
||||
return {
|
||||
read: tagsReadStub
|
||||
};
|
||||
});
|
||||
|
||||
sinon.stub(helpers, 'secure').get(function () {
|
||||
return secureStub;
|
||||
|
@ -66,7 +74,7 @@ describe('Unit - services/routing/controllers/static', function () {
|
|||
render: sinon.spy(),
|
||||
redirect: sinon.spy(),
|
||||
locals: {
|
||||
apiVersion: 'v0.1'
|
||||
apiVersion: 'v2'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -78,7 +86,7 @@ describe('Unit - services/routing/controllers/static', function () {
|
|||
it('no extra data to fetch', function (done) {
|
||||
helpers.renderer.callsFake(function () {
|
||||
helpers.formatResponse.entries.calledOnce.should.be.true();
|
||||
api.tags.read.called.should.be.false();
|
||||
tagsReadStub.called.should.be.false();
|
||||
helpers.secure.called.should.be.false();
|
||||
done();
|
||||
});
|
||||
|
@ -89,7 +97,7 @@ describe('Unit - services/routing/controllers/static', function () {
|
|||
it('extra data to fetch', function (done) {
|
||||
res.routerOptions.data = {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
controller: 'tagsPublic',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
|
@ -98,10 +106,10 @@ describe('Unit - services/routing/controllers/static', function () {
|
|||
}
|
||||
};
|
||||
|
||||
api.tags.read.resolves({tags: [{slug: 'bacon'}]});
|
||||
tagsReadStub = sinon.stub().resolves({tags: [{slug: 'bacon'}]});
|
||||
|
||||
helpers.renderer.callsFake(function () {
|
||||
api.tags.read.called.should.be.true();
|
||||
tagsReadStub.called.should.be.true();
|
||||
helpers.formatResponse.entries.calledOnce.should.be.true();
|
||||
helpers.secure.calledOnce.should.be.true();
|
||||
done();
|
||||
|
|
|
@ -286,7 +286,7 @@ describe('Contexts', function () {
|
|||
|
||||
it('should correctly identify AMP page', function () {
|
||||
res.locals.relativeUrl = '/welcome-to-ghost/amp/';
|
||||
data.post = testUtils.DataGenerator.forKnex.createPost({page: true});
|
||||
data.page = testUtils.DataGenerator.forKnex.createPost({page: true});
|
||||
|
||||
delete res.routerOptions;
|
||||
helpers.context(req, res, data);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
const should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
api = require('../../../../../server/api')['v0.1'],
|
||||
helpers = require('../../../../../frontend/services/routing/helpers'),
|
||||
testUtils = require('../../../../utils');
|
||||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
const api = require('../../../../../server/api').v2;
|
||||
const helpers = require('../../../../../frontend/services/routing/helpers');
|
||||
const testUtils = require('../../../../utils');
|
||||
|
||||
describe('Unit - services/routing/helpers/fetch-data', function () {
|
||||
let posts, tags, locals;
|
||||
let browsePostsStub, readTagsStub;
|
||||
|
||||
beforeEach(function () {
|
||||
posts = [
|
||||
|
@ -22,19 +23,28 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
testUtils.DataGenerator.forKnex.createTag()
|
||||
];
|
||||
|
||||
sinon.stub(api.posts, 'browse')
|
||||
.resolves({
|
||||
posts: posts,
|
||||
meta: {
|
||||
pagination: {
|
||||
pages: 2
|
||||
}
|
||||
browsePostsStub = sinon.stub().resolves({
|
||||
posts: posts,
|
||||
meta: {
|
||||
pagination: {
|
||||
pages: 2
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
sinon.stub(api, 'postsPublic').get(() => {
|
||||
return {
|
||||
browse: browsePostsStub
|
||||
};
|
||||
});
|
||||
|
||||
sinon.stub(api.tags, 'read').resolves({tags: tags});
|
||||
readTagsStub = sinon.stub().resolves({tags: tags});
|
||||
sinon.stub(api, 'tagsPublic').get(() => {
|
||||
return {
|
||||
read: readTagsStub
|
||||
};
|
||||
});
|
||||
|
||||
locals = {apiVersion: 'v0.1'};
|
||||
locals = {apiVersion: 'v2'};
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
@ -47,10 +57,10 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
result.should.be.an.Object().with.properties('posts', 'meta');
|
||||
result.should.not.have.property('data');
|
||||
|
||||
api.posts.browse.calledOnce.should.be.true();
|
||||
api.posts.browse.firstCall.args[0].should.be.an.Object();
|
||||
api.posts.browse.firstCall.args[0].should.have.property('include');
|
||||
api.posts.browse.firstCall.args[0].should.not.have.property('filter');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].should.be.an.Object();
|
||||
browsePostsStub.firstCall.args[0].should.have.property('include');
|
||||
browsePostsStub.firstCall.args[0].should.not.have.property('filter');
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -64,11 +74,11 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
|
||||
result.posts.length.should.eql(posts.length);
|
||||
|
||||
api.posts.browse.calledOnce.should.be.true();
|
||||
api.posts.browse.firstCall.args[0].should.be.an.Object();
|
||||
api.posts.browse.firstCall.args[0].should.have.property('include');
|
||||
api.posts.browse.firstCall.args[0].should.have.property('limit', 10);
|
||||
api.posts.browse.firstCall.args[0].should.have.property('page', 2);
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].should.be.an.Object();
|
||||
browsePostsStub.firstCall.args[0].should.have.property('include');
|
||||
browsePostsStub.firstCall.args[0].should.have.property('limit', 10);
|
||||
browsePostsStub.firstCall.args[0].should.have.property('page', 2);
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
@ -102,11 +112,10 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
// @TODO v3 will deprecate this style (featured.posts)
|
||||
result.data.featured.posts.length.should.eql(posts.length);
|
||||
|
||||
api.posts.browse.calledTwice.should.be.true();
|
||||
api.posts.browse.firstCall.args[0].should.have.property('include', 'author,authors,tags');
|
||||
|
||||
api.posts.browse.secondCall.args[0].should.have.property('filter', 'featured:true');
|
||||
api.posts.browse.secondCall.args[0].should.have.property('limit', 3);
|
||||
browsePostsStub.calledTwice.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].should.have.property('include', 'authors,tags');
|
||||
browsePostsStub.secondCall.args[0].should.have.property('filter', 'featured:true');
|
||||
browsePostsStub.secondCall.args[0].should.have.property('limit', 3);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
@ -139,11 +148,11 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
// @TODO v3 will deprecate this style (featured.posts)
|
||||
result.data.featured.posts.length.should.eql(posts.length);
|
||||
|
||||
api.posts.browse.calledTwice.should.be.true();
|
||||
api.posts.browse.firstCall.args[0].should.have.property('include', 'author,authors,tags');
|
||||
api.posts.browse.firstCall.args[0].should.have.property('page', 2);
|
||||
api.posts.browse.secondCall.args[0].should.have.property('filter', 'featured:true');
|
||||
api.posts.browse.secondCall.args[0].should.have.property('limit', 3);
|
||||
browsePostsStub.calledTwice.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].should.have.property('include', 'authors,tags');
|
||||
browsePostsStub.firstCall.args[0].should.have.property('page', 2);
|
||||
browsePostsStub.secondCall.args[0].should.have.property('filter', 'featured:true');
|
||||
browsePostsStub.secondCall.args[0].should.have.property('limit', 3);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
@ -157,7 +166,7 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
filter: 'tags:%s',
|
||||
data: {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
controller: 'tagsPublic',
|
||||
type: 'read',
|
||||
resource: 'tags',
|
||||
options: {slug: '%s'}
|
||||
|
@ -173,11 +182,11 @@ describe('Unit - services/routing/helpers/fetch-data', function () {
|
|||
result.posts.length.should.eql(posts.length);
|
||||
result.data.tag.length.should.eql(tags.length);
|
||||
|
||||
api.posts.browse.calledOnce.should.be.true();
|
||||
api.posts.browse.firstCall.args[0].should.have.property('include');
|
||||
api.posts.browse.firstCall.args[0].should.have.property('filter', 'tags:testing');
|
||||
api.posts.browse.firstCall.args[0].should.not.have.property('slug');
|
||||
api.tags.read.firstCall.args[0].should.have.property('slug', 'testing');
|
||||
browsePostsStub.calledOnce.should.be.true();
|
||||
browsePostsStub.firstCall.args[0].should.have.property('include');
|
||||
browsePostsStub.firstCall.args[0].should.have.property('filter', 'tags:testing');
|
||||
browsePostsStub.firstCall.args[0].should.not.have.property('slug');
|
||||
readTagsStub.firstCall.args[0].should.have.property('slug', 'testing');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
|
|
@ -21,787 +21,6 @@ describe('UNIT: services/settings/validate', function () {
|
|||
sinon.restore();
|
||||
});
|
||||
|
||||
describe('v0.1', function () {
|
||||
before(function () {
|
||||
apiVersion = 'v0.1';
|
||||
});
|
||||
|
||||
it('no type definitions / empty yaml file', function () {
|
||||
const object = validate({});
|
||||
|
||||
object.should.eql({collections: {}, routes: {}, taxonomies: {}});
|
||||
});
|
||||
|
||||
it('throws error when using :\w+ notiation in collection', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/magic/{slug}/'
|
||||
},
|
||||
'/': {
|
||||
permalink: '/:slug/'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error when using :\w+ notiation in taxonomies', function () {
|
||||
try {
|
||||
validate({
|
||||
taxonomies: {
|
||||
tag: '/categories/:slug/'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error when using an undefined taxonomy', function () {
|
||||
try {
|
||||
validate({
|
||||
taxonomies: {
|
||||
sweet_baked_good: '/patisserie/{slug}'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error when permalink is missing (collection)', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
permalink: '/{slug}/'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without leading or trailing slashes', function () {
|
||||
try {
|
||||
validate({
|
||||
routes: {
|
||||
about: 'about'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without trailing slash', function () {
|
||||
try {
|
||||
validate({
|
||||
routes: {
|
||||
'/about': 'about'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without leading slashe', function () {
|
||||
try {
|
||||
validate({
|
||||
routes: {
|
||||
'about/': 'about'
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without leading slash with permalink', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'magic/': {
|
||||
permalink: '/{slug}/'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without leading or trailing slashes with permalink', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
magic: {
|
||||
permalink: '/{slug}/'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without trailing slash with permalink', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic': {
|
||||
permalink: '/{slug}/'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without trailing slash in permalink', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('throws error without leading or trailing slashes in permalink', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '{slug}'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('no validation error for routes', function () {
|
||||
validate({
|
||||
routes: {
|
||||
'/': 'home'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('no validation error for / collection', function () {
|
||||
validate({
|
||||
collections: {
|
||||
'/': {
|
||||
permalink: '/{primary_tag}/{slug}/'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('transforms {.*} notation into :\w+', function () {
|
||||
const object = validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/magic/{year}/{slug}/'
|
||||
},
|
||||
'/': {
|
||||
permalink: '/{slug}/'
|
||||
}
|
||||
},
|
||||
taxonomies: {
|
||||
tag: '/tags/{slug}/',
|
||||
author: '/authors/{slug}/'
|
||||
}
|
||||
});
|
||||
|
||||
object.should.eql({
|
||||
routes: {},
|
||||
taxonomies: {
|
||||
tag: '/tags/:slug/',
|
||||
author: '/authors/:slug/'
|
||||
},
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/magic/:year/:slug/',
|
||||
templates: []
|
||||
},
|
||||
'/': {
|
||||
permalink: '/:slug/',
|
||||
templates: []
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('template definitions', function () {
|
||||
it('single value', function () {
|
||||
const object = validate({
|
||||
routes: {
|
||||
'/about/': 'about',
|
||||
'/me/': {
|
||||
template: 'me'
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/': {
|
||||
permalink: '/{slug}/',
|
||||
template: 'test'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
object.should.eql({
|
||||
taxonomies: {},
|
||||
routes: {
|
||||
'/about/': {
|
||||
templates: ['about']
|
||||
},
|
||||
'/me/': {
|
||||
templates: ['me']
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/': {
|
||||
permalink: '/:slug/',
|
||||
templates: ['test']
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('array', function () {
|
||||
const object = validate({
|
||||
routes: {
|
||||
'/about/': 'about',
|
||||
'/me/': {
|
||||
template: ['me']
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/': {
|
||||
permalink: '/{slug}/',
|
||||
template: ['test']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
object.should.eql({
|
||||
taxonomies: {},
|
||||
routes: {
|
||||
'/about/': {
|
||||
templates: ['about']
|
||||
},
|
||||
'/me/': {
|
||||
templates: ['me']
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/': {
|
||||
permalink: '/:slug/',
|
||||
templates: ['test']
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('data definitions', function () {
|
||||
it('shortform', function () {
|
||||
const object = validate({
|
||||
routes: {
|
||||
'/food/': {
|
||||
data: 'tag.food'
|
||||
},
|
||||
'/music/': {
|
||||
data: 'tag.music'
|
||||
},
|
||||
'/ghost/': {
|
||||
data: 'user.ghost'
|
||||
},
|
||||
'/sleep/': {
|
||||
data: {
|
||||
bed: 'tag.bed',
|
||||
dream: 'tag.dream'
|
||||
}
|
||||
},
|
||||
'/lala/': {
|
||||
data: 'author.carsten'
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/more/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
home: 'page.home'
|
||||
}
|
||||
},
|
||||
'/podcast/': {
|
||||
permalink: '/podcast/{slug}/',
|
||||
data: {
|
||||
something: 'tag.something'
|
||||
}
|
||||
},
|
||||
'/': {
|
||||
permalink: '/{slug}/',
|
||||
data: 'tag.sport'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
object.should.eql({
|
||||
taxonomies: {},
|
||||
routes: {
|
||||
'/food/': {
|
||||
data: {
|
||||
query: {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'food',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
tags: [{redirect: true, slug: 'food'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/ghost/': {
|
||||
data: {
|
||||
query: {
|
||||
user: {
|
||||
controller: 'users',
|
||||
resource: 'users',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'ghost',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
authors: [{redirect: true, slug: 'ghost'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/music/': {
|
||||
data: {
|
||||
query: {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'music',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
tags: [{redirect: true, slug: 'music'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/sleep/': {
|
||||
data: {
|
||||
query: {
|
||||
bed: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'bed',
|
||||
visibility: 'public'
|
||||
}
|
||||
},
|
||||
dream: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'dream',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
tags: [{redirect: true, slug: 'bed'}, {redirect: true, slug: 'dream'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/lala/': {
|
||||
data: {
|
||||
query: {
|
||||
author: {
|
||||
controller: 'users',
|
||||
resource: 'users',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'carsten',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
authors: [{redirect: true, slug: 'carsten'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/more/': {
|
||||
permalink: '/:slug/',
|
||||
data: {
|
||||
query: {
|
||||
home: {
|
||||
controller: 'posts',
|
||||
resource: 'posts',
|
||||
type: 'read',
|
||||
options: {
|
||||
page: 1,
|
||||
slug: 'home',
|
||||
status: 'published'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
posts: [{redirect: true, slug: 'home'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/podcast/': {
|
||||
permalink: '/podcast/:slug/',
|
||||
data: {
|
||||
query: {
|
||||
something: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'something',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
tags: [{redirect: true, slug: 'something'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/': {
|
||||
permalink: '/:slug/',
|
||||
data: {
|
||||
query: {
|
||||
tag: {
|
||||
controller: 'tags',
|
||||
resource: 'tags',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'sport',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
tags: [{redirect: true, slug: 'sport'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('longform', function () {
|
||||
const object = validate({
|
||||
routes: {
|
||||
'/food/': {
|
||||
data: {
|
||||
food: {
|
||||
resource: 'posts',
|
||||
type: 'browse'
|
||||
}
|
||||
}
|
||||
},
|
||||
'/wellness/': {
|
||||
data: {
|
||||
posts: {
|
||||
resource: 'posts',
|
||||
type: 'read',
|
||||
redirect: false
|
||||
}
|
||||
}
|
||||
},
|
||||
'/partyparty/': {
|
||||
data: {
|
||||
people: {
|
||||
resource: 'users',
|
||||
type: 'read',
|
||||
slug: 'djgutelaune',
|
||||
redirect: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/yoga/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
gym: {
|
||||
resource: 'posts',
|
||||
type: 'read',
|
||||
slug: 'ups',
|
||||
status: 'draft'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
object.should.eql({
|
||||
taxonomies: {},
|
||||
routes: {
|
||||
'/food/': {
|
||||
data: {
|
||||
query: {
|
||||
food: {
|
||||
controller: 'posts',
|
||||
resource: 'posts',
|
||||
type: 'browse',
|
||||
options: {}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
posts: [{redirect: true}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/wellness/': {
|
||||
data: {
|
||||
query: {
|
||||
posts: {
|
||||
controller: 'posts',
|
||||
resource: 'posts',
|
||||
type: 'read',
|
||||
options: {
|
||||
status: 'published',
|
||||
slug: '%s',
|
||||
page: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
posts: [{redirect: false}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
},
|
||||
'/partyparty/': {
|
||||
data: {
|
||||
query: {
|
||||
people: {
|
||||
controller: 'users',
|
||||
resource: 'users',
|
||||
type: 'read',
|
||||
options: {
|
||||
slug: 'djgutelaune',
|
||||
visibility: 'public'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
authors: [{redirect: true, slug: 'djgutelaune'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
}
|
||||
},
|
||||
collections: {
|
||||
'/yoga/': {
|
||||
permalink: '/:slug/',
|
||||
data: {
|
||||
query: {
|
||||
gym: {
|
||||
controller: 'posts',
|
||||
resource: 'posts',
|
||||
type: 'read',
|
||||
options: {
|
||||
page: 0,
|
||||
slug: 'ups',
|
||||
status: 'draft'
|
||||
}
|
||||
}
|
||||
},
|
||||
router: {
|
||||
posts: [{redirect: true, slug: 'ups'}]
|
||||
}
|
||||
},
|
||||
templates: []
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('errors: data shortform incorrect', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}/',
|
||||
data: 'tag:test'
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('errors: data longform resource is missing', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
type: 'edit'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('errors: data longform type is missing', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
resource: 'subscribers'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('errors: data longform name is author', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
author: {
|
||||
resource: 'users'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
|
||||
it('errors: data longform does not use a custom name at all', function () {
|
||||
try {
|
||||
validate({
|
||||
collections: {
|
||||
'/magic/': {
|
||||
permalink: '/{slug}/',
|
||||
data: {
|
||||
resource: 'users'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
(err instanceof common.errors.ValidationError).should.be.true();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('should fail');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('v2', function () {
|
||||
before(function () {
|
||||
apiVersion = 'v2';
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"demo": "https://demo.ghost.io",
|
||||
"version": "2.4.2",
|
||||
"engines": {
|
||||
"ghost": ">=2.0.0"
|
||||
"ghost": ">=2.0.0",
|
||||
"ghost-api": "v2"
|
||||
},
|
||||
"license": "MIT",
|
||||
"screenshots": {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"demo": "https://demo.ghost.io",
|
||||
"version": "2.4.2",
|
||||
"engines": {
|
||||
"ghost": ">=2.0.0"
|
||||
"ghost": ">=2.0.0",
|
||||
"ghost-api": "v2"
|
||||
},
|
||||
"license": "MIT",
|
||||
"screenshots": {
|
||||
|
|
Loading…
Add table
Reference in a new issue