mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-27 04:43:12 +03:00
59fe794b0c
refs: https://github.com/TryGhost/Team/issues/3139 https://github.com/TryGhost/Team/issues/3140 - Added duplicate post functionality to post list context menu - Currently only a single post can be duplicated at a time - Currently only enabled via the `Making it rain` flag - Added admin API endpoint to copy a post - `POST ghost/api/admin/posts/<post_id>/copy/` - Added admin API endpoint to copy a page - `POST ghost/api/admin/pages/<page_id>/copy/`
248 lines
7.8 KiB
JavaScript
248 lines
7.8 KiB
JavaScript
const {PostsService} = require('../index');
|
|
const assert = require('assert');
|
|
const sinon = require('sinon');
|
|
|
|
describe('Posts Service', function () {
|
|
it('Can construct class', function () {
|
|
new PostsService({});
|
|
});
|
|
|
|
describe('shouldSendEmail', function () {
|
|
it('calculates if an email should be sent', async function () {
|
|
const postsService = new PostsService({});
|
|
|
|
assert.deepEqual([
|
|
postsService.shouldSendEmail('published', 'draft'),
|
|
postsService.shouldSendEmail('published', 'scheduled'),
|
|
postsService.shouldSendEmail('sent', 'draft'),
|
|
postsService.shouldSendEmail('sent', 'scheduled'),
|
|
|
|
postsService.shouldSendEmail('published', 'published'),
|
|
postsService.shouldSendEmail('published', 'sent'),
|
|
postsService.shouldSendEmail('published', 'published'),
|
|
postsService.shouldSendEmail('published', 'sent'),
|
|
postsService.shouldSendEmail('sent', 'published'),
|
|
postsService.shouldSendEmail('sent', 'sent'),
|
|
postsService.shouldSendEmail()
|
|
], [
|
|
true,
|
|
true,
|
|
true,
|
|
true,
|
|
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('copyPost', function () {
|
|
const makeModelStub = (key, value) => ({
|
|
get(k) {
|
|
if (k === key) {
|
|
return value;
|
|
}
|
|
}
|
|
});
|
|
|
|
const POST_ID = 'abc123';
|
|
|
|
let postModelStub, existingPostModel, frame;
|
|
|
|
const makePostService = () => new PostsService({
|
|
models: {
|
|
Post: postModelStub
|
|
}
|
|
});
|
|
|
|
beforeEach(function () {
|
|
postModelStub = {
|
|
add: sinon.stub(),
|
|
findOne: sinon.stub()
|
|
};
|
|
|
|
existingPostModel = {
|
|
attributes: {
|
|
id: POST_ID,
|
|
title: 'Test Post',
|
|
slug: 'test-post',
|
|
status: 'published'
|
|
},
|
|
related: sinon.stub()
|
|
};
|
|
|
|
frame = {
|
|
options: {
|
|
id: POST_ID
|
|
}
|
|
};
|
|
|
|
postModelStub.findOne.withArgs({
|
|
id: POST_ID,
|
|
status: 'all'
|
|
}, frame.options).resolves(existingPostModel);
|
|
|
|
postModelStub.add.resolves();
|
|
|
|
existingPostModel.related.withArgs('authors').returns([]);
|
|
existingPostModel.related.withArgs('tags').returns([]);
|
|
existingPostModel.related.withArgs('posts_meta').returns({
|
|
isNew: () => true
|
|
});
|
|
existingPostModel.related.withArgs('tiers').returns([]);
|
|
});
|
|
|
|
it('copies a post', async function () {
|
|
const copiedPost = {
|
|
attributes: {
|
|
id: 'def789'
|
|
}
|
|
};
|
|
|
|
postModelStub.add.resolves(copiedPost);
|
|
|
|
const result = await makePostService().copyPost(frame);
|
|
|
|
// Ensure copied post is created
|
|
assert.equal(
|
|
postModelStub.add.calledOnceWithExactly(
|
|
sinon.match.object,
|
|
frame.options
|
|
),
|
|
true
|
|
);
|
|
|
|
// Ensure copied post is returned
|
|
assert.deepEqual(result, copiedPost);
|
|
});
|
|
|
|
it('omits unnecessary data from the copied post', async function () {
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.equal(copiedPostData.id, undefined);
|
|
assert.equal(copiedPostData.slug, undefined);
|
|
});
|
|
|
|
it('updates the title of the copied post', async function () {
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.equal(copiedPostData.title, 'Test Post (Copy)');
|
|
});
|
|
|
|
it('updates the status of the copied post', async function () {
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.equal(copiedPostData.status, 'draft');
|
|
});
|
|
|
|
it('adds authors to the copied post', async function () {
|
|
existingPostModel.related.withArgs('authors').returns([
|
|
makeModelStub('id', 'author-1'),
|
|
makeModelStub('id', 'author-2')
|
|
]);
|
|
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.deepEqual(copiedPostData.authors, [
|
|
{id: 'author-1'},
|
|
{id: 'author-2'}
|
|
]);
|
|
});
|
|
|
|
it('adds tags to the copied post', async function () {
|
|
existingPostModel.related.withArgs('tags').returns([
|
|
makeModelStub('id', 'tag-1'),
|
|
makeModelStub('id', 'tag-2')
|
|
]);
|
|
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.deepEqual(copiedPostData.tags, [
|
|
{id: 'tag-1'},
|
|
{id: 'tag-2'}
|
|
]);
|
|
});
|
|
|
|
it('adds meta data to the copied post', async function () {
|
|
const postMetaModel = {
|
|
attributes: {
|
|
meta_title: 'Test Post',
|
|
meta_description: 'Test Post Description'
|
|
},
|
|
isNew: () => false
|
|
};
|
|
|
|
existingPostModel.related.withArgs('posts_meta').returns(postMetaModel);
|
|
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.deepEqual(copiedPostData.posts_meta, postMetaModel.attributes);
|
|
});
|
|
|
|
it('adds tiers to the copied post', async function () {
|
|
existingPostModel.related.withArgs('tiers').returns([
|
|
makeModelStub('id', 'tier-1'),
|
|
makeModelStub('id', 'tier-2')
|
|
]);
|
|
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.deepEqual(copiedPostData.tiers, [
|
|
{id: 'tier-1'},
|
|
{id: 'tier-2'}
|
|
]);
|
|
});
|
|
|
|
it('omits unnecessary meta data from the copied post', async function () {
|
|
const postMetaModel = {
|
|
attributes: {
|
|
post_id: POST_ID,
|
|
meta_title: 'Test Post',
|
|
meta_description: 'Test Post Description'
|
|
},
|
|
isNew: () => false
|
|
};
|
|
|
|
existingPostModel.related.withArgs('posts_meta').returns(postMetaModel);
|
|
|
|
await makePostService().copyPost(frame);
|
|
|
|
const copiedPostData = postModelStub.add.getCall(0).args[0];
|
|
|
|
assert.deepEqual(copiedPostData.posts_meta, {
|
|
meta_title: postMetaModel.attributes.meta_title,
|
|
meta_description: postMetaModel.attributes.meta_description
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('generateCopiedPostLocationFromUrl', function () {
|
|
it('generates a location from the provided url', function () {
|
|
const postsService = new PostsService({});
|
|
const url = 'http://foo.bar/ghost/api/admin/posts/abc123/copy/def456/';
|
|
const expectedUrl = 'http://foo.bar/ghost/api/admin/posts/def456/';
|
|
|
|
assert.equal(postsService.generateCopiedPostLocationFromUrl(url), expectedUrl);
|
|
});
|
|
});
|
|
});
|