Skip to content

Commit

Permalink
Merge branch 'master' @ 2.19.0 into stable
Browse files Browse the repository at this point in the history
* master:
  Version bump to 2.19.0
  Updated Ghost-Admin to 2.19.0
  Migrated asset and author helpers to es6 (#10611)
  🐛 Fixed AMP output when there is a trailing '$'
  Model regression tests cleanup (#10639)
  • Loading branch information
allouis committed Mar 26, 2019
2 parents c71127f + 00a5275 commit 1fc9e60
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 603 deletions.
2 changes: 1 addition & 1 deletion core/client
12 changes: 6 additions & 6 deletions core/server/helpers/asset.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// # Asset helper
// Usage: `{{asset "css/screen.css"}}`, `{{asset "css/screen.css" ghost="true"}}`
// Usage: `{{asset "css/screen.css"}}`
//
// Returns the path to the specified asset. The ghost flag outputs the asset path for the Ghost admin
const proxy = require('./proxy'),
get = require('lodash/get'),
getAssetUrl = proxy.metaData.getAssetUrl,
SafeString = proxy.SafeString;
// Returns the path to the specified asset.
const proxy = require('./proxy');
const get = require('lodash/get');
const {SafeString} = proxy;
const {getAssetUrl} = proxy.metaData;

module.exports = function asset(path, options) {
const hasMinFile = get(options, 'hash.hasMinFile');
Expand Down
44 changes: 24 additions & 20 deletions core/server/helpers/authors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,31 @@
// By default, authors are separated by commas.
//
// Note that the standard {{#each authors}} implementation is unaffected by this helper.
const proxy = require('./proxy'),
_ = require('lodash'),
urlService = require('../services/url'),
SafeString = proxy.SafeString,
templates = proxy.templates,
models = proxy.models;

module.exports = function authors(options) {
options = options || {};
options.hash = options.hash || {};
const proxy = require('./proxy');
const _ = require('lodash');
const urlService = require('../services/url');
const {SafeString, templates, models} = proxy;

const autolink = !(_.isString(options.hash.autolink) && options.hash.autolink === 'false'),
separator = _.isString(options.hash.separator) ? options.hash.separator : ', ',
prefix = _.isString(options.hash.prefix) ? options.hash.prefix : '',
suffix = _.isString(options.hash.suffix) ? options.hash.suffix : '',
limit = options.hash.limit ? parseInt(options.hash.limit, 10) : undefined,
visibilityArr = models.Base.Model.parseVisibilityString(options.hash.visibility);
module.exports = function authors(options = {}) {
options.hash = options.hash || {};

let output = '',
from = options.hash.from ? parseInt(options.hash.from, 10) : 1,
to = options.hash.to ? parseInt(options.hash.to, 10) : undefined;
let {
autolink,
separator = ', ',
prefix = '',
suffix = '',
limit,
visibility,
from = 1,
to
} = options.hash;
let output = '';
const visibilityArr = models.Base.Model.parseVisibilityString(visibility);

autolink = !(_.isString(autolink) && autolink === 'false');
limit = limit ? parseInt(limit, 10) : limit;
from = from ? parseInt(from, 10) : from;
to = to ? parseInt(to, 10) : to;

function createAuthorsList(authors) {
function processAuthor(author) {
Expand All @@ -36,7 +40,7 @@ module.exports = function authors(options) {
}) : _.escape(author.name);
}

return models.Base.Model.filterByVisibility(authors, visibilityArr, !!options.hash.visibility, processAuthor);
return models.Base.Model.filterByVisibility(authors, visibilityArr, !!visibility, processAuthor);
}

if (this.authors && this.authors.length) {
Expand Down
118 changes: 112 additions & 6 deletions core/test/regression/api/v2/admin/posts_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ describe('Posts API', function () {
});
});

it('fields combined with formats and include', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title&include=authors'))
it('combined fields, formats, include and non existing', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html,plaintext&fields=id,title,primary_tag,doesnotexist&include=authors,tags'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
Expand All @@ -81,7 +81,7 @@ describe('Posts API', function () {
'post',
null,
null,
['mobiledoc', 'id', 'title', 'html', 'authors']
['mobiledoc', 'plaintext', 'id', 'title', 'html', 'authors', 'tags', 'primary_tag']
);

localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
Expand All @@ -91,7 +91,7 @@ describe('Posts API', function () {
});
});

describe('read', function () {
describe('Read', function () {
it('can\'t retrieve non existent post', function (done) {
request.get(localUtils.API.getApiQuery(`posts/${ObjectId.generate()}/`))
.set('Origin', config.get('url'))
Expand Down Expand Up @@ -123,7 +123,28 @@ describe('Posts API', function () {
});
});

describe('edit', function () {
describe('Add', function () {
it('adds default title when it is missing', function () {
return request
.post(localUtils.API.getApiQuery('posts/'))
.set('Origin', config.get('url'))
.send({
posts: [{
title: '',
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(201)
.then((res) => {
should.exist(res.body.posts);
should.exist(res.body.posts[0].title);
res.body.posts[0].title.should.equal('(Untitled)');
});
});
});

describe('Edit', function () {
it('published_at = null', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
Expand Down Expand Up @@ -151,6 +172,35 @@ describe('Posts API', function () {
});
});

it('html to plaintext', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
.set('Origin', config.get('url'))
.expect(200)
.then((res) => {
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/?source=html&formats=html,plaintext'))
.set('Origin', config.get('url'))
.send({
posts: [{
html: '<p>HTML Ipsum presents</p>',
updated_at: res.body.posts[0].updated_at
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200);
})
.then((res) => {
return models.Post.findOne({
id: res.body.posts[0].id
}, testUtils.context.internal);
})
.then((model) => {
model.get('plaintext').should.equal('HTML Ipsum presents');
});
});

it('canonical_url', function () {
return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
Expand Down Expand Up @@ -236,9 +286,65 @@ describe('Posts API', function () {
should.exist(res.headers['x-cache-invalidate']);
});
});

it('trims title', function () {
const untrimmedTitle = ' test trimmed update title ';

return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
.set('Origin', config.get('url'))
.expect(200)
.then((res) => {
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.send({
posts: [{
title: untrimmedTitle,
updated_at: res.body.posts[0].updated_at
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200);
})
.then((res) => {
should.exist(res.body.posts);
should.exist(res.body.posts[0].title);
res.body.posts[0].title.should.equal(untrimmedTitle.trim());
});
});

it('strips invisible unicode from slug', function () {
const slug = 'this-is\u0008-invisible';

return request
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
.set('Origin', config.get('url'))
.expect(200)
.then((res) => {
return request
.put(localUtils.API.getApiQuery('posts/' + testUtils.DataGenerator.Content.posts[0].id + '/'))
.set('Origin', config.get('url'))
.send({
posts: [{
slug: slug,
updated_at: res.body.posts[0].updated_at
}]
})
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200);
})
.then((res) => {
should.exist(res.body.posts);
should.exist(res.body.posts[0].slug);
res.body.posts[0].slug.should.equal('this-is-invisible');
});
});
});

describe('destroy', function () {
describe('Destroy', function () {
it('non existent post', function () {
return request
.del(localUtils.API.getApiQuery('posts/' + ObjectId.generate() + '/'))
Expand Down
Loading

0 comments on commit 1fc9e60

Please sign in to comment.