mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Model regression tests cleanup (#10639)
refs #9178 - Migrated settings model regression to unit tests - Removed redundant/unuseful post tests - Extracted post model regression tests to API tests - Renamed test suites for consistency
This commit is contained in:
parent
6629b4d490
commit
c219446f85
5 changed files with 249 additions and 570 deletions
|
@ -59,8 +59,8 @@ describe('Posts API', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fields combined with formats and include', function (done) {
|
it('combined fields, formats, include and non existing', function (done) {
|
||||||
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title&include=authors'))
|
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html,plaintext&fields=id,title,primary_tag,doesnotexist&include=authors,tags'))
|
||||||
.set('Origin', config.get('url'))
|
.set('Origin', config.get('url'))
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('Cache-Control', testUtils.cacheRules.private)
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
||||||
|
@ -81,7 +81,7 @@ describe('Posts API', function () {
|
||||||
'post',
|
'post',
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
['mobiledoc', 'id', 'title', 'html', 'authors']
|
['mobiledoc', 'plaintext', 'id', 'title', 'html', 'authors', 'tags', 'primary_tag']
|
||||||
);
|
);
|
||||||
|
|
||||||
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
localUtils.API.checkResponse(jsonResponse.meta.pagination, 'pagination');
|
||||||
|
@ -91,7 +91,7 @@ describe('Posts API', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('read', function () {
|
describe('Read', function () {
|
||||||
it('can\'t retrieve non existent post', function (done) {
|
it('can\'t retrieve non existent post', function (done) {
|
||||||
request.get(localUtils.API.getApiQuery(`posts/${ObjectId.generate()}/`))
|
request.get(localUtils.API.getApiQuery(`posts/${ObjectId.generate()}/`))
|
||||||
.set('Origin', config.get('url'))
|
.set('Origin', config.get('url'))
|
||||||
|
@ -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 () {
|
it('published_at = null', function () {
|
||||||
return request
|
return request
|
||||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||||
|
@ -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 () {
|
it('canonical_url', function () {
|
||||||
return request
|
return request
|
||||||
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
.get(localUtils.API.getApiQuery(`posts/${testUtils.DataGenerator.Content.posts[0].id}/`))
|
||||||
|
@ -236,9 +286,65 @@ describe('Posts API', function () {
|
||||||
should.exist(res.headers['x-cache-invalidate']);
|
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 () {
|
it('non existent post', function () {
|
||||||
return request
|
return request
|
||||||
.del(localUtils.API.getApiQuery('posts/' + ObjectId.generate() + '/'))
|
.del(localUtils.API.getApiQuery('posts/' + ObjectId.generate() + '/'))
|
||||||
|
|
|
@ -38,50 +38,6 @@ describe('Post Model', function () {
|
||||||
sinon.stub(urlService, 'getUrlByResourceId').withArgs(testUtils.DataGenerator.Content.posts[0].id).returns('/html-ipsum/');
|
sinon.stub(urlService, 'getUrlByResourceId').withArgs(testUtils.DataGenerator.Content.posts[0].id).returns('/html-ipsum/');
|
||||||
});
|
});
|
||||||
|
|
||||||
function checkFirstPostData(firstPost, options) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
should.not.exist(firstPost.author_id);
|
|
||||||
firstPost.author.should.be.an.Object();
|
|
||||||
|
|
||||||
if (options.withRelated && options.withRelated.indexOf('authors') !== -1) {
|
|
||||||
firstPost.authors.length.should.eql(1);
|
|
||||||
firstPost.authors[0].should.eql(firstPost.author);
|
|
||||||
}
|
|
||||||
|
|
||||||
firstPost.tags.should.be.an.Array();
|
|
||||||
|
|
||||||
firstPost.author.name.should.equal(DataGenerator.Content.users[0].name);
|
|
||||||
firstPost.created_at.should.be.an.instanceof(Date);
|
|
||||||
firstPost.created_by.should.be.an.Object();
|
|
||||||
firstPost.updated_by.should.be.an.Object();
|
|
||||||
firstPost.published_by.should.be.an.Object();
|
|
||||||
firstPost.created_by.name.should.equal(DataGenerator.Content.users[0].name);
|
|
||||||
firstPost.updated_by.name.should.equal(DataGenerator.Content.users[0].name);
|
|
||||||
firstPost.published_by.name.should.equal(DataGenerator.Content.users[0].name);
|
|
||||||
firstPost.tags[0].name.should.equal(DataGenerator.Content.tags[0].name);
|
|
||||||
firstPost.custom_excerpt.should.equal(DataGenerator.Content.posts[0].custom_excerpt);
|
|
||||||
|
|
||||||
if (options.formats) {
|
|
||||||
if (options.formats.indexOf('mobiledoc') !== -1) {
|
|
||||||
firstPost.mobiledoc.should.match(/HTML Ipsum Presents/);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.formats.indexOf('html') !== -1) {
|
|
||||||
firstPost.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.formats.indexOf('plaintext') !== -1) {
|
|
||||||
firstPost.plaintext.should.match(/HTML Ipsum Presents/);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
firstPost.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
should.equal(firstPost.plaintext, undefined);
|
|
||||||
should.equal(firstPost.mobiledoc, undefined);
|
|
||||||
should.equal(firstPost.amp, undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Single author posts', function () {
|
describe('Single author posts', function () {
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
configUtils.restore();
|
configUtils.restore();
|
||||||
|
@ -99,110 +55,7 @@ describe('Post Model', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findAll', function () {
|
|
||||||
it('can findAll, returning all related data', function (done) {
|
|
||||||
var options = {withRelated: ['author', 'authors', 'tags', 'created_by', 'updated_by', 'published_by']};
|
|
||||||
|
|
||||||
models.Post.findAll(options)
|
|
||||||
.then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
results.length.should.be.above(0);
|
|
||||||
|
|
||||||
var posts = results.models.map(function (model) {
|
|
||||||
return model.toJSON();
|
|
||||||
}), firstPost = _.find(posts, {title: testUtils.DataGenerator.Content.posts[0].title});
|
|
||||||
|
|
||||||
checkFirstPostData(firstPost, options);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can findAll, use formats option', function (done) {
|
|
||||||
var options = {
|
|
||||||
formats: ['mobiledoc', 'plaintext'],
|
|
||||||
withRelated: ['author', 'fields', 'tags', 'created_by', 'updated_by', 'published_by']
|
|
||||||
};
|
|
||||||
|
|
||||||
models.Post.findAll(options)
|
|
||||||
.then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
results.length.should.be.above(0);
|
|
||||||
|
|
||||||
var posts = results.models.map(function (model) {
|
|
||||||
return model.toJSON(options);
|
|
||||||
}), firstPost = _.find(posts, {title: testUtils.DataGenerator.Content.posts[0].title});
|
|
||||||
|
|
||||||
checkFirstPostData(firstPost, options);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('findPage', function () {
|
describe('findPage', function () {
|
||||||
it('can findPage, returning all related data', function (done) {
|
|
||||||
models.Post.findPage({withRelated: ['author', 'fields', 'tags', 'created_by', 'updated_by', 'published_by']})
|
|
||||||
.then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
|
|
||||||
results.meta.pagination.page.should.equal(1);
|
|
||||||
results.meta.pagination.limit.should.equal(15);
|
|
||||||
results.meta.pagination.pages.should.equal(1);
|
|
||||||
results.data.length.should.equal(4);
|
|
||||||
|
|
||||||
var firstPost = _.find(results.data, {attributes:{title: testUtils.DataGenerator.Content.posts[0].title}});
|
|
||||||
checkFirstPostData(firstPost.toJSON());
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns computed fields when columns are asked for explicitly', function (done) {
|
|
||||||
const options = {
|
|
||||||
columns: ['id', 'slug', 'primary_tag'],
|
|
||||||
withRelated: 'tags'
|
|
||||||
};
|
|
||||||
|
|
||||||
models.Post.findPage(options).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
|
|
||||||
var post = _.find(results.data, {attributes: {slug: testUtils.DataGenerator.Content.posts[0].slug}}).toJSON(options);
|
|
||||||
post.primary_tag.slug.should.equal('kitchen-sink');
|
|
||||||
|
|
||||||
// If a computed property is inadvertently passed into a "fetch" operation,
|
|
||||||
// there's a bug in bookshelf where the model will come back with it as
|
|
||||||
// a column enclosed in quotes.
|
|
||||||
should.not.exist(post['"primary_tag"']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ignores columns that do not exist', function (done) {
|
|
||||||
models.Post.findPage({columns: ['id', 'slug', 'doesnotexist']}).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
|
|
||||||
var post = _.find(results.data, {attributes: {slug: testUtils.DataGenerator.Content.posts[0].slug}}).toJSON();
|
|
||||||
post.id.should.equal(testUtils.DataGenerator.Content.posts[0].id);
|
|
||||||
post.slug.should.equal('html-ipsum');
|
|
||||||
should.not.exist(post.doesnotexist);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can NOT findPage for a page that overflows the datatype', function (done) {
|
|
||||||
models.Post.findPage({page: 5700000000055345439587894375457849375284932759842375894372589243758947325894375894275894275894725897432859724309})
|
|
||||||
.then(function (paginationResult) {
|
|
||||||
should.exist(paginationResult.meta);
|
|
||||||
|
|
||||||
paginationResult.meta.pagination.page.should.be.a.Number();
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
// @TODO: this test case fails for mysql currently if you run all regression tests, the test does not fail if you run this as a single test
|
// @TODO: this test case fails for mysql currently if you run all regression tests, the test does not fail if you run this as a single test
|
||||||
describe.skip('with more posts/tags', function () {
|
describe.skip('with more posts/tags', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
@ -329,22 +182,6 @@ describe('Post Model', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findOne', function () {
|
|
||||||
it('can findOne, returning all related data', function (done) {
|
|
||||||
var firstPost;
|
|
||||||
|
|
||||||
models.Post.findOne({}, {withRelated: ['author', 'fields', 'tags', 'created_by', 'updated_by', 'published_by']})
|
|
||||||
.then(function (result) {
|
|
||||||
should.exist(result);
|
|
||||||
firstPost = result.toJSON();
|
|
||||||
|
|
||||||
checkFirstPostData(firstPost);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('edit', function () {
|
describe('edit', function () {
|
||||||
|
@ -457,83 +294,6 @@ describe('Post Model', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[success] custom excerpt soft limit respected', function (done) {
|
|
||||||
var postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
||||||
|
|
||||||
models.Post.findOne({id: postId}).then(function (results) {
|
|
||||||
var post;
|
|
||||||
should.exist(results);
|
|
||||||
post = results.toJSON();
|
|
||||||
post.id.should.equal(postId);
|
|
||||||
|
|
||||||
return models.Post.edit({
|
|
||||||
custom_excerpt: new Array(300).join('a')
|
|
||||||
}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
edited.get('custom_excerpt').length.should.eql(299);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can change title to number', function (done) {
|
|
||||||
var postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
||||||
|
|
||||||
models.Post.findOne({id: postId}).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
var post = results.toJSON();
|
|
||||||
post.title.should.not.equal('123');
|
|
||||||
return models.Post.edit({title: 123}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
edited.attributes.title.should.equal('123');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('converts html to plaintext', function (done) {
|
|
||||||
var postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
||||||
|
|
||||||
models.Post.findOne({id: postId}).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
results.attributes.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
should.exist(results.attributes.plaintext);
|
|
||||||
return models.Post.edit({updated_at: results.attributes.updated_at}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
|
|
||||||
edited.attributes.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
edited.attributes.plaintext.should.match(/HTML Ipsum Presents/);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('converts html to plaintext if html is null', function (done) {
|
|
||||||
var postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
||||||
|
|
||||||
models.Post.findOne({id: postId}).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
results.attributes.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
should.exist(results.attributes.plaintext);
|
|
||||||
return models.Post.edit({updated_at: results.attributes.updated_at}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
|
|
||||||
edited.attributes.html.should.match(/HTML Ipsum Presents/);
|
|
||||||
edited.attributes.plaintext.should.match(/HTML Ipsum Presents/);
|
|
||||||
return edited;
|
|
||||||
}).then(function (edited) {
|
|
||||||
return models.Post.edit({
|
|
||||||
mobiledoc: DataGenerator.markdownToMobiledoc(''),
|
|
||||||
updated_at: edited.attributes.updated_at
|
|
||||||
}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
should.not.exist(edited.attributes.html);
|
|
||||||
should.not.exist(edited.attributes.plaintext);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can publish draft post', function (done) {
|
it('can publish draft post', function (done) {
|
||||||
var postId = testUtils.DataGenerator.Content.posts[3].id;
|
var postId = testUtils.DataGenerator.Content.posts[3].id;
|
||||||
|
|
||||||
|
@ -908,40 +668,6 @@ describe('Post Model', function () {
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can save a draft without setting published_by or published_at', function (done) {
|
|
||||||
var newPost = testUtils.DataGenerator.forModel.posts[2],
|
|
||||||
postId;
|
|
||||||
|
|
||||||
models.Post.add(newPost, context).then(function (results) {
|
|
||||||
var post;
|
|
||||||
should.exist(results);
|
|
||||||
post = results.toJSON();
|
|
||||||
postId = post.id;
|
|
||||||
|
|
||||||
post.status.should.equal('draft');
|
|
||||||
should.not.exist(post.published_by);
|
|
||||||
should.not.exist(post.published_at);
|
|
||||||
|
|
||||||
// Test changing an unrelated property
|
|
||||||
return models.Post.edit({title: 'Hello World'}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
edited.attributes.status.should.equal('draft');
|
|
||||||
should.not.exist(edited.attributes.published_by);
|
|
||||||
should.not.exist(edited.attributes.published_at);
|
|
||||||
|
|
||||||
// Test changing status and published_by on its own
|
|
||||||
return models.Post.edit({published_by: 4}, _.extend({}, context, {id: postId}));
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
edited.attributes.status.should.equal('draft');
|
|
||||||
should.not.exist(edited.attributes.published_by);
|
|
||||||
should.not.exist(edited.attributes.published_at);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cannot override the published_by setting', function (done) {
|
it('cannot override the published_by setting', function (done) {
|
||||||
var postId = testUtils.DataGenerator.Content.posts[3].id;
|
var postId = testUtils.DataGenerator.Content.posts[3].id;
|
||||||
|
|
||||||
|
@ -972,30 +698,6 @@ describe('Post Model', function () {
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('send empty date', function (done) {
|
|
||||||
var postId = testUtils.DataGenerator.Content.posts[0].id;
|
|
||||||
|
|
||||||
models.Post
|
|
||||||
.findOne({
|
|
||||||
id: postId
|
|
||||||
})
|
|
||||||
.then(function (results) {
|
|
||||||
var post;
|
|
||||||
should.exist(results);
|
|
||||||
post = results.toJSON();
|
|
||||||
post.id.should.equal(postId);
|
|
||||||
|
|
||||||
return models.Post.edit({created_at: ''}, _.extend({}, context, {id: postId}));
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
done(new Error('This test should fail.'));
|
|
||||||
})
|
|
||||||
.catch(function (err) {
|
|
||||||
err.statusCode.should.eql(422);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('add', function () {
|
describe('add', function () {
|
||||||
|
@ -1084,17 +786,6 @@ describe('Post Model', function () {
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can add, with title being a number', function (done) {
|
|
||||||
var newPost = testUtils.DataGenerator.forModel.posts[2];
|
|
||||||
|
|
||||||
newPost.title = 123;
|
|
||||||
|
|
||||||
models.Post.add(newPost, context).then(function (createdPost) {
|
|
||||||
should.exist(createdPost);
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can add, with previous published_at date', function (done) {
|
it('can add, with previous published_at date', function (done) {
|
||||||
var previousPublishedAtDate = new Date(2013, 8, 21, 12);
|
var previousPublishedAtDate = new Date(2013, 8, 21, 12);
|
||||||
|
|
||||||
|
@ -1227,75 +918,6 @@ describe('Post Model', function () {
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('add scheduled page with published_at 10 minutes in future -> we expect success', function (done) {
|
|
||||||
models.Post.add({
|
|
||||||
status: 'scheduled',
|
|
||||||
page: 1,
|
|
||||||
published_at: moment().add(10, 'minute'),
|
|
||||||
title: 'scheduled 1',
|
|
||||||
mobiledoc: markdownToMobiledoc('This is some content')
|
|
||||||
}, context).then(function (post) {
|
|
||||||
should.exist(post);
|
|
||||||
|
|
||||||
Object.keys(eventsTriggered).length.should.eql(3);
|
|
||||||
should.exist(eventsTriggered['page.added']);
|
|
||||||
should.exist(eventsTriggered['page.scheduled']);
|
|
||||||
should.exist(eventsTriggered['user.attached']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can add default title, if it\'s missing', function (done) {
|
|
||||||
models.Post.add({
|
|
||||||
mobiledoc: markdownToMobiledoc('Content')
|
|
||||||
}, context).then(function (newPost) {
|
|
||||||
should.exist(newPost);
|
|
||||||
newPost.get('title').should.equal('(Untitled)');
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can trim title', function (done) {
|
|
||||||
var untrimmedCreateTitle = ' test trimmed create title ',
|
|
||||||
untrimmedUpdateTitle = ' test trimmed update title ',
|
|
||||||
newPost = {
|
|
||||||
title: untrimmedCreateTitle,
|
|
||||||
mobiledoc: markdownToMobiledoc('Test content')
|
|
||||||
};
|
|
||||||
|
|
||||||
models.Post.add(newPost, context).then(function (createdPost) {
|
|
||||||
return models.Post.findOne({id: createdPost.id, status: 'all'});
|
|
||||||
}).then(function (createdPost) {
|
|
||||||
should.exist(createdPost);
|
|
||||||
createdPost.get('title').should.equal(untrimmedCreateTitle.trim());
|
|
||||||
|
|
||||||
Object.keys(eventsTriggered).length.should.eql(2);
|
|
||||||
should.exist(eventsTriggered['post.added']);
|
|
||||||
should.exist(eventsTriggered['user.attached']);
|
|
||||||
|
|
||||||
return createdPost.save({title: untrimmedUpdateTitle}, context);
|
|
||||||
}).then(function (updatedPost) {
|
|
||||||
updatedPost.get('title').should.equal(untrimmedUpdateTitle.trim());
|
|
||||||
|
|
||||||
Object.keys(eventsTriggered).length.should.eql(3);
|
|
||||||
should.exist(eventsTriggered['post.edited']);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can strip invisible unicode from slug', function (done) {
|
|
||||||
models.Post.add({
|
|
||||||
slug: 'abc\u0008',
|
|
||||||
}, context).then(function (newPost) {
|
|
||||||
should.exist(newPost);
|
|
||||||
newPost.get('slug').should.equal('abc');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can generate a non conflicting slug', function (done) {
|
it('can generate a non conflicting slug', function (done) {
|
||||||
// Create 12 posts with the same title
|
// Create 12 posts with the same title
|
||||||
sequence(_.times(12, function (i) {
|
sequence(_.times(12, function (i) {
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
var should = require('should'),
|
|
||||||
_ = require('lodash'),
|
|
||||||
sinon = require('sinon'),
|
|
||||||
testUtils = require('../../utils'),
|
|
||||||
SettingsModel = require('../../../server/models/settings').Settings,
|
|
||||||
db = require('../../../server/data/db'),
|
|
||||||
common = require('../../../server/lib/common'),
|
|
||||||
context = testUtils.context.admin;
|
|
||||||
|
|
||||||
describe('Settings Model', function () {
|
|
||||||
var eventSpy;
|
|
||||||
|
|
||||||
// Keep the DB clean
|
|
||||||
before(testUtils.teardown);
|
|
||||||
afterEach(testUtils.teardown);
|
|
||||||
beforeEach(testUtils.setup('settings'));
|
|
||||||
|
|
||||||
before(function () {
|
|
||||||
should.exist(SettingsModel);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
sinon.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
eventSpy = sinon.spy(common.events, 'emit');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('API', function () {
|
|
||||||
it('can edit single', function (done) {
|
|
||||||
SettingsModel.findAll().then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
|
|
||||||
results.length.should.be.above(0);
|
|
||||||
|
|
||||||
return SettingsModel.edit({key: 'description', value: 'new value'}, context);
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
|
|
||||||
edited.length.should.equal(1);
|
|
||||||
|
|
||||||
edited = edited[0];
|
|
||||||
|
|
||||||
edited.attributes.key.should.equal('description');
|
|
||||||
edited.attributes.value.should.equal('new value');
|
|
||||||
|
|
||||||
eventSpy.calledTwice.should.be.true();
|
|
||||||
eventSpy.firstCall.calledWith('settings.edited').should.be.true();
|
|
||||||
eventSpy.secondCall.calledWith('settings.description.edited').should.be.true();
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can edit multiple', function (done) {
|
|
||||||
var model1,
|
|
||||||
model2,
|
|
||||||
editedModel;
|
|
||||||
|
|
||||||
SettingsModel.findAll().then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
|
|
||||||
results.length.should.be.above(0);
|
|
||||||
|
|
||||||
model1 = {key: 'description', value: 'another new value'};
|
|
||||||
model2 = {key: 'title', value: 'new title'};
|
|
||||||
|
|
||||||
return SettingsModel.edit([model1, model2], context);
|
|
||||||
}).then(function (edited) {
|
|
||||||
should.exist(edited);
|
|
||||||
|
|
||||||
edited.length.should.equal(2);
|
|
||||||
|
|
||||||
editedModel = edited[0];
|
|
||||||
|
|
||||||
editedModel.attributes.key.should.equal(model1.key);
|
|
||||||
editedModel.attributes.value.should.equal(model1.value);
|
|
||||||
|
|
||||||
editedModel = edited[1];
|
|
||||||
|
|
||||||
editedModel.attributes.key.should.equal(model2.key);
|
|
||||||
editedModel.attributes.value.should.equal(model2.value);
|
|
||||||
|
|
||||||
eventSpy.callCount.should.equal(4);
|
|
||||||
|
|
||||||
// We can't rely on the order of updates.
|
|
||||||
// We can however expect the first and third call to
|
|
||||||
// to be `settings.edited`.
|
|
||||||
eventSpy.firstCall.calledWith('settings.edited').should.be.true();
|
|
||||||
eventSpy.thirdCall.calledWith('settings.edited').should.be.true();
|
|
||||||
|
|
||||||
eventSpy.calledWith('settings.description.edited').should.be.true();
|
|
||||||
eventSpy.calledWith('settings.title.edited').should.be.true();
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can add', function (done) {
|
|
||||||
var newSetting = {
|
|
||||||
key: 'TestSetting1',
|
|
||||||
value: 'Test Content 1'
|
|
||||||
};
|
|
||||||
|
|
||||||
SettingsModel.add(newSetting, context).then(function (createdSetting) {
|
|
||||||
should.exist(createdSetting);
|
|
||||||
createdSetting.has('uuid').should.equal(false);
|
|
||||||
createdSetting.attributes.key.should.equal(newSetting.key, 'key is correct');
|
|
||||||
createdSetting.attributes.value.should.equal(newSetting.value, 'value is correct');
|
|
||||||
createdSetting.attributes.type.should.equal('core');
|
|
||||||
|
|
||||||
eventSpy.calledTwice.should.be.true();
|
|
||||||
eventSpy.firstCall.calledWith('settings.added').should.be.true();
|
|
||||||
eventSpy.secondCall.calledWith('settings.TestSetting1.added').should.be.true();
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can destroy', function (done) {
|
|
||||||
SettingsModel.findAll().then(function (allSettings) {
|
|
||||||
SettingsModel.findOne({id: allSettings.models[1].id}).then(function (results) {
|
|
||||||
should.exist(results);
|
|
||||||
results.attributes.id.should.equal(allSettings.models[1].id);
|
|
||||||
return SettingsModel.destroy({id: allSettings.models[1].id});
|
|
||||||
}).then(function (response) {
|
|
||||||
response.toJSON().should.be.empty();
|
|
||||||
return SettingsModel.findOne({id: allSettings.models[1].id});
|
|
||||||
}).then(function (newResults) {
|
|
||||||
should.equal(newResults, null);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('populating defaults from settings.json', function () {
|
|
||||||
beforeEach(function (done) {
|
|
||||||
db.knex('settings').truncate().then(function () {
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('populates any unset settings from the JSON defaults', function (done) {
|
|
||||||
SettingsModel.findAll().then(function (allSettings) {
|
|
||||||
allSettings.length.should.equal(0);
|
|
||||||
return SettingsModel.populateDefaults();
|
|
||||||
}).then(function () {
|
|
||||||
return SettingsModel.findAll();
|
|
||||||
}).then(function (allSettings) {
|
|
||||||
allSettings.length.should.be.above(0);
|
|
||||||
|
|
||||||
return SettingsModel.findOne('description');
|
|
||||||
}).then(function (descriptionSetting) {
|
|
||||||
// Testing against the actual value in default-settings.json feels icky,
|
|
||||||
// but it's easier to fix the test if that ever changes than to mock out that behaviour
|
|
||||||
descriptionSetting.get('value').should.equal('The professional publishing platform');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('doesn\'t overwrite any existing settings', function (done) {
|
|
||||||
SettingsModel.add({key: 'description', value: 'Adam\'s Blog'}, context).then(function () {
|
|
||||||
return SettingsModel.populateDefaults();
|
|
||||||
}).then(function () {
|
|
||||||
return SettingsModel.findOne('description');
|
|
||||||
}).then(function (descriptionSetting) {
|
|
||||||
descriptionSetting.get('value').should.equal('Adam\'s Blog');
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -208,17 +208,6 @@ describe('User Model', function run() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can NOT findPage for a page that overflows the datatype', function (done) {
|
|
||||||
UserModel.findPage({page: 5700000000055345439587894375457849375284932759842375894372589243758947325894375894275894275894725897432859724309})
|
|
||||||
.then(function (paginationResult) {
|
|
||||||
should.exist(paginationResult.meta);
|
|
||||||
|
|
||||||
paginationResult.meta.pagination.page.should.be.a.Number();
|
|
||||||
|
|
||||||
done();
|
|
||||||
}).catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can findOne by role name', function () {
|
it('can findOne by role name', function () {
|
||||||
return testUtils.fixtures.createExtraUsers().then(function () {
|
return testUtils.fixtures.createExtraUsers().then(function () {
|
||||||
return Promise.join(UserModel.findOne({role: 'Owner'}), UserModel.findOne({role: 'Editor'}));
|
return Promise.join(UserModel.findOne({role: 'Owner'}), UserModel.findOne({role: 'Editor'}));
|
||||||
|
|
|
@ -1,11 +1,148 @@
|
||||||
const should = require('should');
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
const mockDb = require('mock-knex');
|
||||||
const models = require('../../../server/models');
|
const models = require('../../../server/models');
|
||||||
|
const {knex} = require('../../../server/data/db');
|
||||||
|
const common = require('../../../server/lib/common');
|
||||||
|
|
||||||
describe('Unit: models/settings', function () {
|
describe('Unit: models/settings', function () {
|
||||||
before(function () {
|
before(function () {
|
||||||
models.init();
|
models.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('events', function () {
|
||||||
|
let tracker;
|
||||||
|
let eventSpy;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDb.mock(knex);
|
||||||
|
tracker = mockDb.getTracker();
|
||||||
|
tracker.install();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
mockDb.unmock(knex);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
eventSpy = sinon.spy(common.events, 'emit');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits add events', function () {
|
||||||
|
tracker.on('query', (query, step) => {
|
||||||
|
return [
|
||||||
|
function fetchAddQuery() {
|
||||||
|
query.response([{}]);
|
||||||
|
},
|
||||||
|
function addQuery() {
|
||||||
|
query.response([{
|
||||||
|
key: 'description',
|
||||||
|
value: 'added value'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
][step - 1]();
|
||||||
|
});
|
||||||
|
|
||||||
|
return models.Settings.edit({
|
||||||
|
key: 'description',
|
||||||
|
value: 'added value'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
eventSpy.calledTwice.should.be.true();
|
||||||
|
eventSpy.firstCall.calledWith('settings.added').should.be.true();
|
||||||
|
eventSpy.secondCall.calledWith('settings.description.added').should.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits edit events', function () {
|
||||||
|
tracker.on('query', (query, step) => {
|
||||||
|
return [
|
||||||
|
function fetchEditQuery() {
|
||||||
|
query.response([{
|
||||||
|
id: 1, // NOTE: `id` imitates existing value for 'edit' event
|
||||||
|
key: 'description',
|
||||||
|
value: 'db value'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
][step - 1]();
|
||||||
|
});
|
||||||
|
|
||||||
|
return models.Settings.edit({
|
||||||
|
key: 'description',
|
||||||
|
value: 'edited value'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
eventSpy.calledTwice.should.be.true();
|
||||||
|
eventSpy.firstCall.calledWith('settings.edited').should.be.true();
|
||||||
|
eventSpy.secondCall.calledWith('settings.description.edited').should.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('defaults', function () {
|
||||||
|
let tracker;
|
||||||
|
let eventSpy;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDb.mock(knex);
|
||||||
|
tracker = mockDb.getTracker();
|
||||||
|
tracker.install();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
mockDb.unmock(knex);
|
||||||
|
tracker.uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
eventSpy = sinon.spy(common.events, 'emit');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('populates unset defaults', function () {
|
||||||
|
tracker.on('query', (query) => {
|
||||||
|
return query.response([{}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return models.Settings.populateDefaults()
|
||||||
|
.then(() => {
|
||||||
|
eventSpy.callCount.should.equal(64);
|
||||||
|
|
||||||
|
eventSpy.args[1][0].should.equal('settings.db_hash.added');
|
||||||
|
eventSpy.args[1][1].attributes.type.should.equal('core');
|
||||||
|
|
||||||
|
eventSpy.args[11][0].should.equal('settings.description.added');
|
||||||
|
eventSpy.args[11][1].attributes.type.should.equal('blog');
|
||||||
|
eventSpy.args[11][1].attributes.value.should.equal('The professional publishing platform');
|
||||||
|
|
||||||
|
eventSpy.args[63][0].should.equal('settings.members_subscription_settings.added');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('doesn\'t overwrite any existing settings', function () {
|
||||||
|
tracker.on('query', (query) => {
|
||||||
|
return query.response([{
|
||||||
|
key: 'description',
|
||||||
|
value: 'Adam\'s Blog'
|
||||||
|
}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return models.Settings.populateDefaults()
|
||||||
|
.then(() => {
|
||||||
|
eventSpy.callCount.should.equal(62);
|
||||||
|
|
||||||
|
eventSpy.args[11][0].should.equal('settings.logo.added');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('parse', function () {
|
describe('parse', function () {
|
||||||
it('ensure correct parsing when fetching from db', function () {
|
it('ensure correct parsing when fetching from db', function () {
|
||||||
const setting = models.Settings.forge();
|
const setting = models.Settings.forge();
|
||||||
|
|
Loading…
Add table
Reference in a new issue